У меня есть этот массив символа 3 x 3, это, как предполагается, представляет tic-tac-toe плату, и прежде, я использовал бы набор "если" операторы, чтобы видеть, было ли 3 подряд.
... если ((плата [0] [0] == плата [0] [1]) && (плата [0] [1] == плата [0] [2])) {...}...
Я понял, что это - большой ввод, и довольно подверженный ошибкам, так там лучший способ сделать это?
Вы можете изменить его на проверку только с того места, где был сделан последний ход.
//lr = lastMoveRow
//lc = lastMoveCol
// no need to check blank with last move known
if (board[0][lc] == board[1][lc] && board[0][lc] == board[2][lc] ||
board[lr][0] == board[lr][1] && board[lr][0] == board[lr][2]){
// Game over
}
// Check diagonals
if (board[1][1] != blank &&
(board[0][0] == board[1][1] && board[0][0] == board[2][2] ||
board[2][0] == board[1][1] && board[2][0] == board[0][2])){
// Game over
}
Или - Проверка всех состояний:
//Check horizontals and verticals at once
for (int i = 0; i < 3; ++i){
// Check column and row at once
if (board[0][i] != blank && board[0][i] == board[1][i] && board[0][i] == board[2][i] ||
board[i][0] != blank && board[i][0] == board[i][1] && board[i][0] == board[i][2]){
// Game over
}
}
// Check diagonals
if (board[1][1] != blank &&
(board[0][0] == board[1][1] && board[0][0] == board[2][2] ||
board[2][0] == board[1][1] && board[2][0] == board[0][2])){
// Game over
}
Или, если вы все же превратите это в побитовую систему - держите отдельные доски X и O для простоты обновления. Тогда вам нужно всего 9 бит для x, 9 бит для O, и ваши выигрышные матчи досок будут намного проще. (Чтобы найти открытые места в данном случае, просто поразрядно или доски x и o)
// winning 9 bit boards
// int winningBoards[8]
000000111
000111000
111000000
001001001
010010010
100100100
100010001
001010100
//xBoard and yBoard can be ints
for (int i = 0; i < 8; ++i){
if (xBoard & winningBoards[i] == winningBoards[i]){
//Game over
}
}
Вы можете убрать парантезу, потому что &&
имеет более низкий приоритет, чем ==
if (board[0][0] == board[0][1] && board[0][1] == board[0][2])
Вы также можете определить встроенную функцию (или макрос) для проверки равенства
inline bool are_equal(int a, int b, int c) {
return a == b && b == c;
}
...
if (are_equal(board[0][0], board[0][1], board[0][2]))
Обратите внимание, что a==b==c
не возвращает то, что вам нужно. Например, 0==0==1
верно во многих языках, производных от языка Си.
Вы можете зациклить это. Например, чтобы проверить все строки, вы можете сделать:
for(int i = 0; i < 3; i++){
if((board[i][0]==board[i][1]) && (board[i][1]==board[i][2])){
....
}
}
И сделать что-то подобное для столбцов. Тогда вам просто нужно отдельно проверить диагонали.
Я не знаю насчет «лучше», но вы можете разбить вещи последовательно:
//Set empty to whatever value you're using for an empty square.
#define empty '\0'
bool thereIsALine(char matrix[3][3])
{
char c;
//Check all columns:
for(int i = 0; i < 3; i++)
{
c = matrix[i][0];
if (c == empty)
break;
if (c == matrix[i][1] && c == matrix[i][2])
return true;
}
//Check all rows:
for(int i = 0; i < 3; i++)
{
c = matrix[0][i];
if (c == empty)
break;
if (c == matrix[1][i] && c == matrix[2][i])
return true;
}
//Check diagonals
c = matrix[1][1];
if (c == empty) return false;
if (c == matrix[0][2] && c == matrix[2][0] )
return true;
if (c == matrix[0][0] && c == matrix[2][2] )
return true;
return false;
}
Адаптировано из соревнований Code Golf прошлой недели. Обратите внимание, что линейные узоры вдоль матрицы доски начинаются с заданного индекса и продвигаются по равным интервалам.
И если вы обозначите игрока 1 цифрой 1, а игрока 2 цифрой 2, то это независимые биты, и вы можете проверить их на 3 подряд с помощью побитового AND.
char check_1row( char *board, int base, int stride ) {
return board[ base ] & board[ base + stride ] & board[ base + 2 * stride ];
}
char check_win( char (&board)[3][3] ) {
char winner = 0;
winner |= check1row( board, 0, 4 ); // check NW/SE diagonal
for ( int i = 0; i < 3; i ++ ) {
winner |= check1row( board, i, 3 ); // check verticals
}
winner |= check1row( board, 2, 2 ); // check NE/SW diagonal
for ( int i = 0; i < 9; i += 3 ) {
winner |= check1row( board, i, 1 ); // check horizontals
}
return winner;
}
Вы можете хранить индексы, составляющие выигрышные ряды, и использовать один цикл:
int win_row[][3] = {{0, 0, 0}, {1, 1, 1}, {2, 2, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}};
int win_col[][3] = {{0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 0, 0}, {1, 1, 1}, {2, 2, 2}, {0, 1, 2}, {2, 1, 0}};
bool has_winner(char board[][3])
{
//'\0' means unoccupied
for (int i = 0; i != 8; ++i) {
char c = board[win_row[i][0]][win_col[i][0]];
if (c && c == board[win_row[i][1]][win_col[i][1]] && c == board[win_row[i][2]][win_col[i][2]]) {
return true;
}
}
return false;
}
Я также поддерживаю предложения Джеффа о хранении ходов игроков в отдельных значениях и использовании битовых операций.
Как с помощью загрузить сценарий ?
Что основано на Flash и jQuery, которые могут предложить вам сохранить файл на компьютере.
Downloadify.create('downloadify',{
filename: function(){
return document.getElementById('filename').value;
},
data: function(){
return document.getElementById('data').value;
},
onComplete: function(){
alert('Your File Has Been Saved!');
},
onCancel: function(){
alert('You have cancelled the saving of this file.');
},
onError: function(){
alert('You must put something in the File Contents or there will be nothing to save!');
},
swf: 'media/downloadify.swf',
downloadImage: 'images/download.png',
width: 100,
height: 30,
transparent: true,
append: false
});
-121--2586919- Использование BitConverter , ref: http://msdn.microsoft.com/en-us/library/bb311038.aspx
byte[] vals = { 0x01, 0xAA, 0xB1, 0xDC, 0x10, 0xDD };
var str = BitConverter.ToString(vals).Replace("-", "");
Console.WriteLine(str);
/*Output:
01AAB1DC10DD
*/
-121--5044310- Да, вы могли бы сделать это
if (board[0][0]==board[0][1]==board[0][2]) {...}
Возможно, даже написать функцию
inline boolean row_win(int row_num){
return (board[row_num][0]==board[row_num][1]==board[row_num][2]);
}
Она имеет скрытую сторону, хотя,
Альтернативой является запись цикла for, но я думаю, что это еще больше набора.
Вот полное решение в виде функции проверки, которая проверяет, выигрывает ли игрок (1 или 2, обозначающие X и O):
// tic tac toe win checker
#include<iostream>
using namespace std;
const int DIM = 3;
int check (int t[DIM][DIM]) {
// 0 is empty, 1 is X, 2 is O
// return 1 or 2 if there is a win from either
for (int row=0; row<DIM; row++) {
if (t[row][0] == t[row][1] && t[row][1] == t[row][2]) {
if (t[row][0] != 0) return t[row][0];
}
}
for (int col=0; col<DIM; col++) {
if (t[0][col] == t[1][col] && t[0][col] == t[2][col]) {
if (t[0][col] != 0) return t[0][col];
}
}
if (t[0][0] == t[1][1] && t[1][1] == t[2][2]) {
if (t[0][0] != 0) return t[0][0];
}
if (t[0][2] == t[1][1] && t[1][1] == t[2][0] != 0) {
if (t[0][2] != 0) return t[0][2];
}
return 1;
}
int main() {
int ttt[DIM][DIM];
ttt[1][0] = 2; // Initialyzing row no. 2 to values "2" to test
ttt[1][1] = 2;
ttt[1][2] = 2;
if (check(ttt) != 0) {
cout << "Player " << check(ttt) << " wins\n";
}
else {
cout << "No winner yet\n";
}
}
РЕДАКТИРОВАТЬ: Я предпочел этот подход (возвращение номера выигравшего игрока), а не просто проверку наличия победителя, поскольку он казался более практичным для использования.
Надеюсь, это поможет!