пишу хрестики-нолики, задание на 1 курсе, знаком с языком недавно
самое волнительное происходит в функциях game_over... мне нужно передавать их значения в функцию 'prova', чтобы выяснять в мэйне, продолжится игра или будет иной исход. Подскажите, как это сделать с помощью указателей (тема мимо меня прошла). Буду очень благодарен.
#include <iostream>
#include <windows.h>
#include <math.h>
#include <ctime>
#include <conio.h>
#include <string>
using namespace std;
int map[3][3]; //нули
void map_show() //вывод массива
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (map[i][j] == 0)
cout << "| ";
if (map[i][j] == 1)
cout << "|X";
if (map[i][j] == 2)
cout << "|0";
}
cout << "|" <<endl;
cout << "--------" <<endl;
}
}
void newmap()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
map[i][j]=0;
}
}
}
void hodkomp(int n)
{
int i, j, k = 0; //строки,столбцы,переменная определяющая ходил ли копм
int vs; //соперник
if (n == 1)
{
vs = 2;
}
if (n == 2)
{
vs = 1;
}//проверяем против кого мы играем
//прописываем победные ходы по строкам
for (i = 0; i < 3; i++)
{
if (map[i][0] == n && map[i][1] == n && map[i][2] == 0 && k == 0)
{
map[i][2] = n;
k = 1;
}
if (map[i][0] == n && map[i][1] == 0 && map[i][2] == n && k == 0)
{
map[i][2] = n;
k = 1;
}
if (map[i][0] == 0 && map[i][1] == n && map[i][2] == n && k == 0)
{
map[i][0] = n;
k = 1;
}
}
//победные ходы по столбцам
for (j = 0; j < 3; j++)
{
if (map[0][j] == n && map[1][j] == n && map[2][j] == 0 && k == 0)
{
map[2][j] = n;
k = 1;
}
if (map[i][j] == n && map[1][j] == 0 && map[2][j] == n && k == 0)
{
map[1][j] = n;
k = 1;
}
if (map[0][j] == 0 && map[1][j] == n && map[2][j] == n && k == 0)
{
map[0][j] = n;
k = 1;
}
}
//проверка диагоналей на победный ход
if (map[0][0] == n && map[1][1] == n && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
if (map[0][0] == n && map[1][1] == 0 && map[2][2] == n && k == 0)
{
map[1][1] = n;
k = 1;
}
if (map[0][0] == 0 && map[1][1] == n && map[2][2] == n && k == 0)
{
map[0][0] = n;
k = 1;
}
if (map[0][0] == n && map[1][1] == n && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
if (map[0][0] == n && map[1][1] == n && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
// блокируем противника
// проверяем все строки и выбираем оптимальный ход для компьютера
for (j = 0; j < 3; j++)
{
if (map[0][j] == vs && map[1][j] == vs && map[2][j] == 0 && k == 0)
{
map[2][j] = n;
k = 1;
}
if (map[0][j] == vs && map[1][j] == 0 && map[2][j] == vs && k == 0)
{
map[1][j] = n;
k = 1;
}
if (map[0][j] == 0 && map[1][j] == vs && map[2][j] == vs && k == 0)
{
map[0][j] = n;
k = 1;
}
}
for (i = 0; i < 3; i++)
{
if (map[i][0] == vs && map[i][1] == vs && map[i][2] == 0 && k == 0)
{
map[i][2] = n;
k = 1;
}
if (map[i][0] == vs && map[i][1] == 0 && map[i][2] == vs && k == 0)
{
map[i][1] = n;
k = 1;
}
if (map[i][0] == 0 && map[i][1] == vs && map[i][2] == vs && k == 0)
{
map[i][0] = n;
k = 1;
}
}
//блок диагоналей
if (map[0][0] == vs && map[1][1] == vs && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
if (map[0][0] == vs && map[1][1] == 0 && map[2][2] == vs && k == 0)
{
map[1][1] = n;
k = 1;
}
if (map[0][0] == 0 && map[1][1] == vs && map[2][2] == vs && k == 0)
{
map[0][0] = n;
k = 1;
}
if (map[0][0] == vs && map[1][1] == vs && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
if (map[0][0] == vs && map[1][1] == vs && map[2][2] == 0 && k == 0)
{
map[2][2] = n;
k = 1;
}
// если свободен центр, занимаем его
if (k == 0 && map[1][1] == 0)
{
map[1][1] = n;
k = 1;
}
// если свободно занимаем углы
if (k == 0 && map[0][0] == 0)
{
map[0][0] = n;
k = 1;
}
// если свободно занимаем углы
if (k == 0 && map[0][2] == 0)
{
map[0][2] = n;
k = 1;
}
// если свободно занимаем углы
if (k == 0 && map[2][0] == 0)
{
map[2][0] = n;
k = 1;
}
// если свободно занимаем углы
if (k == 0 && map[2][2] == 0)
{
map[2][2] = n;
k = 1;
}
// случайный выбор свободного места
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (map[i][j] == 0 && k == 0)
{
map[i][j] = n;
k = 1;
}
}
}
if (k == 0)
{
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (map[i][j] == 0 && k == 0)
{
map[i][j] = n;
k = 1;
}
}
}
}
}
int game_over_krest()
{
int keystr = 0; //счетчтк заполненных строк
int keystb = 0;
int keydiaglav = 0;
int keydiapob = 0;
int chek = 0;
//проверка выигрыша строчек
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 3; i++)
{
if (map[i][j] == 1) //подсчет единиц в строке
keystr++;
if (map[j][i] == 1) //подсчет единиц в стлб
keystb++;
if (map[i][i] == 1) //подсчет единиц в главной диагонали
keydiaglav++;
if (map[2 - i][i] == 1)
keydiapob++;
}
if (keystr == 3 || keystb == 3 || keydiaglav == 3 || keydiapob == 3)
{
chek = 1; //крестик
break; //чтобы внешний цикл не выводил 3 раза
}
keystr = 0;
keystb = 0;
keydiaglav = 0;
keydiapob = 0;
}
return chek;
}
int game_over_null()
{
int keystr = 0; //счетчтк заполненных строк
int keystb = 0;
int keydiaglav = 0;
int keydiapob = 0;
int chek = 0;
//проверка выигрыша строчек
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 3; i++)
{
if (map[i][j] == 2) //подсчет единиц в строке
keystr++;
if (map[j][i] == 2) //подсчет единиц в стлб
keystb++;
if (map[i][i] == 2) //подсчет единиц в главной диагонали
keydiaglav++;
if (map[2 - i][i] == 2)
keydiapob++;
}
if (keystr == 3 || keystb == 3 || keydiaglav == 3 || keydiapob == 3)
{
chek = 2; //крестик
break; //чтобы внешний цикл не выводил 3 раза
}
keystr = 0;
keystb = 0;
keydiaglav = 0;
keydiapob = 0;
}
return chek;
}
int game_over_all()
{
int chek=0;
if (chek == 0 && map[0][0] * map[0][1] * map[0][2] & map[1][0] * map[1][1] * map[1][2] * map[2][0] * map[2][1] * map[2][2] > 0)
chek = 3;
return chek;
}
void chel(int n)
{
int i=0, j=0;
int x = 0;
int y = 0; //переменные для координат
cout << "Enter x and y: ";
cin >> x >> y;
if (n == 1 && map[i][j] == 0)
{
map[x-1][y-1] = 1;
}
if (n == 2 && map[ i][j] == 0)
{
map[x-1][y-1] = 2;
}
}
int prova(int chek)
{
while (chek == 0) //действия человека
{
if (game_over_krest() == 1)
{
chek == 1;
break;
}
if (game_over_null() == 2)
{
chek = 2;
break;
}
if (game_over_all() == 3)
{
chek = 3;
break;
}
}
return chek;
}
//первый индекс x, второй у (i столб)
int main()
{
setlocale(LC_ALL, "rus");
int n;//за кого играем
int v;//будем ли играть ещё
int igra;// состояние игры если победил нолик то 1, если победил крестик то 2
int prvvod;//проверка ввода
v = 1;
while (v == 1)
{
cout << "За кого хотите начать? крестики-1, нолики-2\n";
cin >> n;
newmap();
map_show();
igra = 0;
while (igra == 0) //пока никто не победил
{
if (n == 1) //крестики
{
chel(1);
map_show();
igra = prova(1 || 2 || 3);
if (igra == 0)
{
cout << "Ходит компьютер\n";
hodkomp(2);
map_show();
igra = prova(1 || 2 || 3);
}
}
if (n == 2) //нолики
{
cout << "Ходит компьютер\n";
hodkomp(1);
map_show();
igra = prova(1||2||3);
if (igra == 0)
{
chel(2);
map_show();
igra = prova(1 || 2 || 3);
}
}
}
if (igra == 1)
{
cout << "Победил крестик\n";
}
if (igra == 2)
{
cout << "Победил нолик\n";
}
if (igra == 3)
{
cout << "Ничья\n";
}
cout << "Сыграем ещё? 1-да. 2-нет\n";
cin >> v;
}
}
Ответы (2 шт):
Если я правильно вас понял, то вы хотите вместо return возвращает результат функции через указатель. (Если это не так отпишите)
Тогда приведу пример на одной из вашей функции game_over_all (с другими аналогично).
Для начала заголовок функции должен иметь следующий вид:
void game_over_all(int* res)
То есть теперь функцию ничего не будет возвращать, но будет принимать указатель на переменную куда запишет свой результат.
В самой функции вместо return нужно присвоить res посчитанное значение chek. Для этого нужно использовать операцию разыменования.
*res = check;
*res - операция разыменования указателя. При помощи этой операции вы можете или присвоить, или получить значение на которое указывает указатель.
В функции prova вам обязательно нужно создать проинициализированную переменную и передавать в функцию game_over_all указатель на неё, примерно так.
int res = 0;
...
game_over_all(&res)
if(res == 3) ...
& - оператор адреса. Логично предположить, что этот оператор позволяет получить адрес переменной.
Поподробней сразу и об операторе адреса и об операторе разыменования можете почитать тут
И все таки порекомендовал бы пожалеть своего преподавателя и заодно самому потренироваться, и написать более красивый и понятный код.
Лови готовый код
"use strict";
let ticTakToe = { gameTableElement: document.getElementById('game'), status: 'playing', mapValues: [ ['', '', ''], ['', '', ''], ['', '', ''], ], phase: 'X',
/**
* Инициализация игры.
*/
init() {
// Выводим все ячейки.
this.renderMap();
// Инициализируем обработчики событий.
this.initEventHandlers();
},
/**
* Вывод ячеек в html.
*/
renderMap() {
for (let row = 0; row < 3; row++) {
const tr = document.createElement('tr');
this.gameTableElement.appendChild(tr);
for (let col = 0; col < 3; col++) {
let td = document.createElement('td');
td.dataset.row = row.toString();
td.dataset.col = col.toString();
tr.appendChild(td);
}
}
},
/**
* Инициализация обработчиков событий.
*/
initEventHandlers() {
// Ставим обработчик, при клике на таблицу вызовется функция this.cellClickHandler.
this.gameTableElement.addEventListener('click', event => this.cellClickHandler(event));
},
/**
* Обработчик события клика.
* @param {MouseEvent} event
*/
cellClickHandler(event) {
// Если клик не нужно обрабатывать, уходим из функции.
if (!this.isCorrectClick(event)) {
return;
}
// Заполняем ячейку.
this.fillCell(event);
// Если кто-то выиграл, заходим в if.
if (this.hasWon()) {
// Ставим статус в "остановлено".
this.setStatusStopped();
// Сообщаем о победе пользователя.
this.sayWonPhrase();
}
// Меняем фигуру (крестик или нолик).
this.togglePhase();
},
/**
* Проверка был ли корректный клик, что описан в событии event.
* @param {Event} event
* @returns {boolean} Вернет true в случае если статус игры "играем", клик что описан в объекте event был
* по ячейке и ячейка куда был произведен клик был по пустой ячейке.
*/
isCorrectClick(event) {
return this.isStatusPlaying() && this.isClickByCell(event) && this.isCellEmpty(event);
},
/**
* Проверка что мы "играем", что игра не закончена.
* @returns {boolean} Вернет true, статус игры "играем", иначе false.
*/
isStatusPlaying() {
return this.status === 'playing';
},
/**
* Проверка что клик был по ячейке.
* @param {Event} event
* @param {HTMLElement} event.target
* @returns {boolean} Вернет true, если клик был по ячейке, иначе false.
*/
isClickByCell(event) {
return event.target.tagName === 'TD';
},
/**
* Проверка что в ячейку не ставили значение (крестик или нолик).
* @param {Event} event
* @param {HTMLElement} event.target
* @returns {boolean} Вернет true, если ячейка пуста, иначе false.
*/
isCellEmpty(event) {
// Получаем строку и колонку куда кликнули.
let row = +event.target.dataset.row;
let col = +event.target.dataset.col;
return this.mapValues[row][col] === '';
},
/**
* Заполняет ячейку в которую кликнул пользователь в событии event.
* @param {Event} event
* @param {HTMLElement} event.target
*/
fillCell(event) {
// Получаем строку и колонку куда кликнули.
let row = +event.target.dataset.row;
let col = +event.target.dataset.col;
// Заполняем ячейку и ставим значение в массиве, в свойстве mapValues.
this.mapValues[row][col] = this.phase;
event.target.textContent = this.phase;
},
/**
* Проверка есть ли выигрышная ситуация на карте.
* @returns {boolean} Вернет true, если игра выиграна, иначе false.
*/
hasWon() {
return this.isLineWon({ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }) ||
this.isLineWon({ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 1 }) ||
this.isLineWon({ x: 0, y: 2 }, { x: 1, y: 2 }, { x: 2, y: 2 }) ||
this.isLineWon({ x: 0, y: 0 }, { x: 0, y: 1 }, { x: 0, y: 2 }) ||
this.isLineWon({ x: 1, y: 0 }, { x: 1, y: 1 }, { x: 1, y: 2 }) ||
this.isLineWon({ x: 2, y: 0 }, { x: 2, y: 1 }, { x: 2, y: 2 }) ||
this.isLineWon({ x: 0, y: 0 }, { x: 1, y: 1 }, { x: 2, y: 2 }) ||
this.isLineWon({ x: 0, y: 2 }, { x: 1, y: 1 }, { x: 2, y: 0 });
},
/**
* Проверка есть ли выигрышная ситуация на линии.
* @param {{x: int, y: int}} a 1-ая ячейка.
* @param {{x: int, y: int}} b 2-ая ячейка.
* @param {{x: int, y: int}} c 3-я ячейка.
* @returns {boolean} Вернет true, если линия выиграна, иначе false.
*/
isLineWon(a, b, c) {
let value = this.mapValues[a.y][a.x] + this.mapValues[b.y][b.x] + this.mapValues[c.y][c.x];
return value === 'XXX' || value === '000';
},
/**
* Ставит статус игры в "остановлена".
*/
setStatusStopped() {
this.status = 'stopped';
},
/**
* Сообщает о победе.
*/
sayWonPhrase() {
let figure = this.phase === 'X' ? 'Крестики' : 'Нолики';
alert(`${figure} выиграли!`);
},
/**
* Меняет фигуру (крестик или нолик).
*/
togglePhase() {
this.phase = this.phase === 'X' ? '0' : 'X';
},
};
ticTakToe.init();