├── README.md
├── .gitignore
├── velha.html
├── css
└── velha.css
└── js
└── velha.js
/README.md:
--------------------------------------------------------------------------------
1 | # jogo-da-velha
2 | Simples jogo da velha feito com HTML, CSS3 e JavaScript
3 |
4 | Este jogo foi feito para práticar com aos alunos lógica de programação com HTML5, CSS3 e JavaScript.
5 | Tudo foi feito de maneira bem simples.
6 |
7 | Atualizado dia 10/12/2021.
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
--------------------------------------------------------------------------------
/velha.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Joguinho da velhinha
7 |
8 |
9 |
10 |
11 |
12 |
13 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/css/velha.css:
--------------------------------------------------------------------------------
1 | /* Aqui eu posso declarar variáveis. */
2 | :root{
3 | --color-primary:rgb(40,140,40);
4 | --color-secundary:rgb(40,100,40);
5 | --color-geral: #121214;
6 | --font-color: rgb(255,255,250);
7 | }
8 |
9 | /* Aqui estou zerando o CSS do navegador */
10 | html, body {
11 | margin: 0;
12 | padding: 0;
13 | width: 100%;
14 | height: 100%;
15 | box-sizing: border-box;
16 | }
17 |
18 | /* meu container principal */
19 | .container {
20 | display: grid;
21 | grid-template-columns: 200px 200px 200px;
22 | grid-template-rows: 20vh 20vh 20vh 20vh calc(20vh - 20px);
23 | background-color: var(--color-geral);
24 | color: var(--font-color);
25 |
26 | grid-template-areas: "h h h"
27 | "v1 v2 v3"
28 | "v4 v5 v6"
29 | "v7 v8 v9"
30 | "f f f";
31 |
32 | grid-gap:5px;
33 | justify-content: center;
34 | align-content: center;
35 | }
36 |
37 | header {
38 | grid-area: h;
39 | display: grid;
40 | grid-gap: 5px;
41 | justify-content: start;
42 | align-content: center;
43 | margin-top: 6px;
44 | }
45 |
46 | footer{
47 | grid-area: f;
48 | text-align: center;
49 | }
50 |
51 | .container > div {
52 | background-color: var(--color-primary);
53 | display: grid;
54 | justify-content: center;
55 | align-content: center;
56 | border-radius: 10px;
57 | font-size: 50px;
58 | font-weight: 800;
59 | }
60 |
61 | .container > div:hover{
62 | background-color: var(--color-secundary);
63 | cursor: pointer;
64 | }
65 |
66 | /* Daqui para baixo CSS especifico */
67 |
68 |
69 |
70 | .opcoes-jogo{
71 | display: grid;
72 | grid-template-columns: 1fr 1fr;
73 | grid-template-rows: 1fr 1fr;
74 | grid-template-areas: "hgx bg"
75 | "hgo bg";
76 |
77 | justify-content: center;
78 | align-content: center;
79 | }
80 |
81 | .header-group #usuario-x{
82 | margin-bottom: 5px;
83 | grid-area: hgx;
84 |
85 | }
86 | .header-group #usuario-O{
87 | margin-bottom: 5px;
88 | grid-area: hgo;
89 |
90 | }
91 |
92 | #btn-jogar{
93 | grid-area: bg;
94 | width: 200px;
95 | height: 120px;
96 | align-self: center;
97 | justify-self: end;
98 | background-color: var(--color-primary);
99 | border:0;
100 | font-size: 20px;
101 | font-weight: 600;
102 | color: var(--font-color);
103 | }
104 |
105 | #btn-jogar:hover{
106 | background-color: var(--color-secundary);
107 | cursor: pointer;
108 | }
109 |
110 | .header-group > label {
111 | font-size: 18px;
112 | }
113 |
114 | .header-group > input {
115 | padding: 5px;
116 | text-transform: none;
117 | text-decoration: none;
118 | border:0;
119 | background-color: transparent;
120 | border: 1px solid var(--color-primary);
121 | color: var(--color-secundary);
122 | font-weight: 800;
123 | font-size: 20px;
124 | margin-left: 15px;
125 | }
126 |
127 | .painel-group{
128 | font-size: 20px;
129 | padding-top: 10px;
130 | }
131 | .pontos{
132 | margin-left: 50px;
133 | float: right;
134 | }
135 | .pontos > strong {
136 | font-size: 20px;
137 | }
138 |
139 | .proximo-jogar{
140 | margin-top: 50px;
141 | }
142 |
143 | .esconder{
144 | display: none;
145 | }
146 |
147 |
--------------------------------------------------------------------------------
/js/velha.js:
--------------------------------------------------------------------------------
1 | // Criando um módulo para deixar o código privado.
2 | (()=>{
3 |
4 | // Declarando variáveis e objetos utilizados para o jogo.
5 | const TEXTO_USUARIO_X = 'Usuário X: ';
6 | const TEXTO_USUARIO_O = 'Usuário O: ';
7 |
8 | let jogadorAtual = {};
9 | let jogadas = [];
10 | let emJogo = false;
11 | let jogo = {
12 | jogada1: document.querySelector('.jogo-velha-1'),
13 | jogada2: document.querySelector('.jogo-velha-2'),
14 | jogada3: document.querySelector('.jogo-velha-3'),
15 | jogada4: document.querySelector('.jogo-velha-4'),
16 | jogada5: document.querySelector('.jogo-velha-5'),
17 | jogada6: document.querySelector('.jogo-velha-6'),
18 | jogada7: document.querySelector('.jogo-velha-7'),
19 | jogada8: document.querySelector('.jogo-velha-8'),
20 | jogada9: document.querySelector('.jogo-velha-9')
21 | }
22 |
23 | let jogadorX = {
24 | nome:'',
25 | valor: 'X',
26 | pontos: 0
27 | }
28 |
29 | let jogadorO = {
30 | nome:'',
31 | valor: 'O',
32 | pontos: 0
33 | }
34 |
35 | var opcoes = {
36 | divOpcoesJogo : document.querySelector('.opcoes-jogo'),
37 | usuarioX : document.getElementById('usuario-x'),
38 | usuarioO : document.getElementById('usuario-o'),
39 | btnJogar : document.getElementById('btn-jogar')
40 | };
41 |
42 | var painel = {
43 | painelOpcoesJogo : document.querySelector('.painel-opcoes'),
44 | nomeX : document.getElementById('painel-usuario-x-nome'),
45 | nomeO : document.getElementById('painel-usuario-o-nome'),
46 | pontosX : document.getElementById('painel-usuario-x-pontos'),
47 | pontosO : document.getElementById('painel-usuario-o-pontos'),
48 | nomeProximoJogador: document.getElementById('proximo-jogador')
49 | };
50 |
51 | // Capturando os eventos de click
52 | opcoes.btnJogar.addEventListener('click', () => {
53 |
54 | jogadorX.nome = opcoes.usuarioX.value;
55 | jogadorO.nome = opcoes.usuarioO.value;
56 |
57 | if(!jogadorX.nome || !jogadorO.nome){
58 | alert('Favor informar os usuarios X e O para iniciar o jogo.');
59 | return;
60 | }
61 |
62 | // Alterar os nomes dos jogadores...
63 | painel.nomeX.textContent = TEXTO_USUARIO_X + jogadorX.nome;
64 | painel.nomeO.textContent = TEXTO_USUARIO_O + jogadorO.nome;
65 |
66 | jogadorAtual = jogadorX;
67 | painel.nomeProximoJogador.textContent = jogadorAtual.nome;
68 | emJogo = true;
69 |
70 | // Aqui tenho que esconder as opções e mostrar o painel.
71 | opcoes.divOpcoesJogo.classList.add('esconder');
72 | painel.painelOpcoesJogo.classList.remove('esconder');
73 | });
74 |
75 |
76 | jogo.jogada1.addEventListener('click', (e)=>{
77 | jogada(e, 1);
78 | });
79 |
80 | jogo.jogada2.addEventListener('click', (e)=>{
81 | jogada(e, 2);
82 | });
83 |
84 | jogo.jogada3.addEventListener('click', (e)=>{
85 | jogada(e, 3);
86 | });
87 |
88 | jogo.jogada4.addEventListener('click', (e)=>{
89 | jogada(e, 4);
90 | });
91 |
92 | jogo.jogada5.addEventListener('click', (e)=>{
93 | jogada(e, 5);
94 | });
95 |
96 | jogo.jogada6.addEventListener('click', (e)=>{
97 | jogada(e, 6);
98 | });
99 |
100 | jogo.jogada7.addEventListener('click', (e)=>{
101 | jogada(e, 7);
102 | });
103 |
104 | jogo.jogada8.addEventListener('click', (e)=>{
105 | jogada(e, 8);
106 | });
107 |
108 | jogo.jogada9.addEventListener('click', (e)=>{
109 | jogada(e, 9);
110 | });
111 |
112 |
113 | // Funções utilizadas no jogo
114 |
115 | function validarJogada(){
116 | let valor = jogadorAtual.valor;
117 |
118 | if(_estrategia_1(valor) ||
119 | _estrategia_2(valor) ||
120 | _estrategia_3(valor) ||
121 | _estrategia_4(valor) ||
122 | _estrategia_5(valor) ||
123 | _estrategia_6(valor) ||
124 | _estrategia_7(valor) ||
125 | _estrategia_8(valor)){
126 |
127 | return true;
128 | }
129 |
130 | return false;
131 | }
132 |
133 | function _estrategia_1(valor){
134 | return (jogadas[1] == valor && jogadas[2] == valor && jogadas[3] == valor);
135 | }
136 | function _estrategia_2(valor){
137 | return (jogadas[4] == valor && jogadas[5] == valor && jogadas[6] == valor);
138 | }
139 | function _estrategia_3(valor){
140 | return (jogadas[7] == valor && jogadas[8] == valor && jogadas[9] == valor);
141 | }
142 | function _estrategia_4(valor){
143 | return (jogadas[1] == valor && jogadas[4] == valor && jogadas[7] == valor);
144 | }
145 | function _estrategia_5(valor){
146 | return (jogadas[2] == valor && jogadas[5] == valor && jogadas[8] == valor);
147 | }
148 | function _estrategia_6(valor){
149 | return (jogadas[3] == valor && jogadas[6] == valor && jogadas[9] == valor);
150 | }
151 | function _estrategia_7(valor){
152 | return (jogadas[1] == valor && jogadas[5] == valor && jogadas[9] == valor);
153 | }
154 | function _estrategia_8(valor){
155 | return (jogadas[3] == valor && jogadas[5] == valor && jogadas[7] == valor);
156 | }
157 |
158 |
159 | function _marcarJogada(e, indice){
160 | e.target.textContent = jogadorAtual.valor;
161 | jogadas[indice] = jogadorAtual.valor;
162 | }
163 |
164 |
165 | function jogada(e, indice){
166 |
167 | if(!emJogo || e.target.textContent){
168 | return;
169 | }
170 |
171 | _marcarJogada(e, indice);
172 |
173 |
174 | if(validarJogada()){
175 |
176 | setTimeout(() =>{
177 | alert(`Parabéns, jogador ${jogadorAtual.nome} acaba de marcar ponto. \\o/`);
178 | _atualizarPainel();
179 | _reiniciarJogo();
180 | }, 100)
181 |
182 | return;
183 | }
184 |
185 | if(jogadas.filter(e => e).length == 9){
186 |
187 | setTimeout(()=>{
188 | alert('Deu velha ...');
189 | _reiniciarJogo();
190 | },100)
191 |
192 | return;
193 | }
194 |
195 | // Continuar jogando.
196 | jogadorAtual = (jogadorAtual == jogadorX) ? jogadorO : jogadorX;
197 |
198 | painel.nomeProximoJogador.textContent = jogadorAtual.nome;
199 | }
200 |
201 | function _reiniciarJogo(){
202 |
203 | jogadas = [];
204 | jogo.jogada1.textContent = '';
205 | jogo.jogada2.textContent = '';
206 | jogo.jogada3.textContent = '';
207 | jogo.jogada4.textContent = '';
208 | jogo.jogada5.textContent = '';
209 | jogo.jogada6.textContent = '';
210 | jogo.jogada7.textContent = '';
211 | jogo.jogada8.textContent = '';
212 | jogo.jogada9.textContent = '';
213 | }
214 |
215 | function _atualizarPainel(){
216 |
217 | jogadorAtual.pontos += 1;
218 |
219 | if(jogadorAtual.valor == "X"){
220 | painel.pontosX.textContent = jogadorAtual.pontos;
221 | }else{
222 | painel.pontosO.textContent = jogadorAtual.pontos;
223 | }
224 |
225 | jogadorAtual = (jogadorAtual == jogadorX) ? jogadorO : jogadorX;
226 | painel.nomeProximoJogador.textContent = jogadorAtual.nome;
227 | }
228 |
229 | })()
--------------------------------------------------------------------------------