Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Елькин Степан Андреевич #67

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
Сейчас в коде описаны функции для рисования поля любого размера и рисования любого символа в клетке этого поля.
Твоя задача дописать код, чтобы это стало полноценной игрой в Крестики-нолики.

1. Реши, как будешь хранить поле. Тебе нужна будет такая структура, в которой удобно понимать есть ли победитель: три клетки по горизонтали, вертикали или диагонали, заполненные одинаковыми символами.
2. Допиши функцию cellClickHandler, чтобы после клика ставился крестик или нолик в соответствующее поле.
3. Если поле, по которому кликнули, не пустое, символ ставиться не должен.
4. Если кончились ходы, выведи alert с текстом "Победила дружба".
5. Напиши функцию, которая считает: есть ли уже победитель. Если есть победитель, выведи alert с названием победителя.
6. Если есть победитель, покрась победные значения в клетках в красный.
7. После победы, клик по полю больше не должен ставить крестик или нолик.
8. Обрабатывай клик по кнопке "Сначала": допиши метод resetClickHandler, чтобы поле очищалось.
9. \* Сделай так, чтобы можно было в начале игры задавать поле произвольного размера.
10. \* Напиши "искусственный интеллект" — функцию, которая будет ставить нолики в случайное пустое поле.
//1. Реши, как будешь хранить поле. Тебе нужна будет такая структура, в которой удобно понимать есть ли победитель: три клетки по горизонтали, вертикали или диагонали, заполненные одинаковыми символами.
//2. Допиши функцию cellClickHandler, чтобы после клика ставился крестик или нолик в соответствующее поле.
//3. Если поле, по которому кликнули, не пустое, символ ставиться не должен.
//4. Если кончились ходы, выведи alert с текстом "Победила дружба".
//5. Напиши функцию, которая считает: есть ли уже победитель. Если есть победитель, выведи alert с названием победителя.
//6. Если есть победитель, покрась победные значения в клетках в красный.
//7. После победы, клик по полю больше не должен ставить крестик или нолик.
//8. Обрабатывай клик по кнопке "Сначала": допиши метод resetClickHandler, чтобы поле очищалось.
//9. \* Сделай так, чтобы можно было в начале игры задавать поле произвольного размера.
//10. \* Напиши "искусственный интеллект" — функцию, которая будет ставить нолики в случайное пустое поле.
11. \* Напиши чуть более умный искусственный интеллект — функция, ставящая нолики в случайном месте обязана поставить нолик в такое поле, нолик в котором приведет к выигрышу "ИИ".
12. \* Сделай так, чтобы при заполнении больше половины клеток на поле, оно бы расширялось: добавлялось бы по одному ряду с каждой стороны.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</div>
<div>
<button class="resetButton" id="reset">Сначала</button>
<button class="AIButton calm" id="startAI">Игра с ботом</button>
</div>
<script src="index.js"></script>
</body>
Expand Down
158 changes: 150 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,35 @@ const ZERO = 'O';
const EMPTY = ' ';

const container = document.getElementById('fieldWrapper');

//генератор случайных челых чисел
const random = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

let table;
let stepCount;
let dim;
let win = false;
let typeOfWin;
let lastRow ;
let lastCol;
let lastSymbol;
let botMode = false;
startGame();
addResetListener();
addAIBotListener();

function startGame () {
renderGrid(3);
renderGrid(prompt("Введите размер поля", 3));
}

function renderGrid (dimension) {
container.innerHTML = '';

stepCount = dimension**2;
dim = dimension;
lastRow = -1;
makeTable();
for (let i = 0; i < dimension; i++) {
const row = document.createElement('tr');
for (let j = 0; j < dimension; j++) {
Expand All @@ -26,14 +44,119 @@ function renderGrid (dimension) {
}
}

function makeTable(){
table = [];
for (let i = 0;i<dim;i++){
let row = [];
for (let j = 0;j<dim;j++){
row.push(EMPTY);
}
table.push(row);
}
}
function stepSequence(){
return stepCount-- % 2 == 0 ? ZERO : CROSS;
}

function findWin(row,col ,symbol){
if (table[row].filter(sym => sym === symbol).length == dim ){
typeOfWin = "row"
return true;
}

let colCount = 0;
for (let i = 0; i < dim; i++){
if (table[i][col] == symbol) colCount++;
}

let countLeft = 0;
let countRight = 0;
let startRow = dim;

for (let i = 0; i < dim; i++){
if (table[i][i] == symbol) countLeft++;
}
for (let j = 0; j < dim; j++){
if (table[--startRow][j] == symbol) countRight++;
console.log(startRow,j);
}

if (countLeft == dim) typeOfWin = "left"
if (countRight == dim) typeOfWin = "right"
if ( colCount == dim) typeOfWin = "column"

return countLeft == dim || countRight == dim || colCount==dim;
}

function cellClickHandler (row, col) {
// Пиши код тут
console.log(`Clicked on cell: ${row}, ${col}`);
if (!win){
cell = table[row][col];

if (stepCount!=0 && cell=== EMPTY){

renderStep(row,col);
if (botMode)
makeBotStep();
}
if (stepCount==0 && !win){
typeOfWin = "friendship"
makeWin();
}
}
}

function renderStep(row,col){
lastSymbol = stepSequence();
lastCol = col;
lastRow = row;
table[row][col] = lastSymbol;
renderSymbolInCell( lastSymbol, row, col);
if (findWin(row,col,lastSymbol)){
makeWin();
botMode = false;
alert(`Победил ${lastSymbol}!`)
}

/* Пользоваться методом для размещения символа в клетке так:
renderSymbolInCell(ZERO, row, col);
*/
}
function makeBotStep(){
while(true){
let rndRow = random(0,dim-1);
let rndCol = random(0,dim-1);
if(table[rndRow][rndCol]==EMPTY){
renderStep(rndRow,rndCol);
return;
}
if (stepCount==0) return;
}
}

function makeWin()
{
win = true;
switch(typeOfWin){
case "row":
for(let i =0 ;i<dim;i++)
renderSymbolInCell(lastSymbol,lastRow,i,'red');
break;
case "column":
for(let i =0 ;i<dim;i++)
renderSymbolInCell(lastSymbol,i,lastCol,'red');
break;
case "left":
for(let i =0 ;i<dim;i++)
renderSymbolInCell(lastSymbol,i,i,'red');
break;
case "right":
let length = dim;
for(let i = 0 ;i<dim;i++)
renderSymbolInCell(lastSymbol,--length,i,'red');
break;
case "friendship":
alert("Победила дружба!");
break;
}
let resetButton = document.querySelector('.resetButton');
resetButton.classList.add('active');
}

function renderSymbolInCell (symbol, row, col, color = '#333') {
Expand All @@ -53,8 +176,27 @@ function addResetListener () {
resetButton.addEventListener('click', resetClickHandler);
}

function addAIBotListener () {
const AIButton = document.getElementById('startAI');
AIButton.onclick = function() {
if (lastRow== -1)
AIButton.classList.add('active');
};
AIButton.addEventListener('click', startAI);
}

function startAI(){
if(!botMode && lastRow== -1) botMode = true;
}

function resetClickHandler () {
console.log('reset!');
win = false;
const AIButton = document.getElementById('startAI');
AIButton.classList.remove('active');
botMode = false;
let resetButton = document.querySelector('.resetButton');
resetButton.classList.remove('active');
startGame();
}


Expand Down
18 changes: 18 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,22 @@ body {
font-size: 16px;
border: 3px solid orange;
border-radius: 5px;
}

.AIButton {
display: block;
margin: 20px auto;
padding: 10px;
background: none;
font-size: 16px;
border: 3px solid orange;
border-radius: 5px;
}

.calm{
background: none;
}

.active{
background: yellowgreen;
}