不需要从头开始每行,每列的判断,和实际的下棋一样,从最后一个落棋的位置开始判断,以它为中心开始的行、列、斜线的去判断是否是相同的棋子相连。缺点是函数的参数会变多。
我这里用棋盘5*5的演示(判断条件还是3个棋子相连)。
假设3-3就是最后一个落棋的坐标,
那么可以从3-1做头:
判断坐标[3][3]是否和坐标[3][1]相等,坐标[3][3]是否和坐标[3][2]相等.
从3-2做头:
判断坐标[3][3]是否和坐标[3][2]相等,坐标[3][3]是否和坐标[3][4]相等.
从3-3做头:
判断坐标[3][3]是否和坐标[3][4]相等,坐标[3][3]是否和坐标[3][5]相等.
列,斜线的判断我就不举例了,下面是完整代码,代码中有具体注释,可以看game.c中最后的部分(代码就测了一两次,有问题可以提一下,电脑还是随机下棋)。
tect.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu();
void game();
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input)
{
printf("\n");
case 1:
game();
break;
case 2:
input = 0;
break;
default:
printf("错误\n");
break;
}
} while (input);
game();
return 0;
}
void menu()
{
printf(" 1. play \n");
printf(" 2. exit \n");
printf(" 选择 \n");
}
void game()
{
//创建一个记录下棋次数的变量,用于判断平局
int count = 0;
//创建一个保存每次下棋位置的数组
int copy[2] = {0};
//创建棋盘
char board[ROW][COL] = { 0 };
//初始化
InitBoard(board, ROW, COL);
//打印
PrintBoard(board, ROW, COL);
//玩家走
while (1)
{
PlayerMove(board, ROW, COL, &count, copy);
PrintBoard(board, ROW, COL);
char ch = Win(board, ROW, COL, copy);
if (ch == '*')
{
printf("play win\n");
printf("\n");
printf("\n");
return;
}
if (count == ROW * COL)
{
printf("平局\n");
printf("\n");
printf("\n");
return;
}
//电脑走
ComputerMove(board, ROW, COL, &count, copy);
PrintBoard(board, ROW, COL);
ch = Win(board, ROW, COL, copy);
if (ch == '#')
{
printf("computer win\n");
printf("\n");
printf("\n");
return;
}
if (count == ROW * COL)
{
printf("平局\n");
printf("\n");
printf("\n");
return;
}
}
}
game.c
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int r = 0; r < row; r++)
{
for (int c = 0; c < col; c++)
{
board[r][c] = ' ';
}
}
}
static void _PrintBoard(char board[ROW][COL], int row, int col)
{
printf(" ");
for (int i = 0; i < col * 4 + 1; i++)
{
printf("-");
}
printf("\n");
}
void PrintBoard(char board[ROW][COL], int row, int col)
{
printf("\n");
printf(" ");
for (int i = 1; i <= col; i++)
{
printf(" %d ", i);
}
printf("\n");
_PrintBoard(board, row, col);
for (int r = 0; r < row; r++)
{
int c = 0;
printf(" %d ", r+1);
for (; c < col; c++)
{
printf("| %c ", board[r][c]);
}
printf("|\n");
_PrintBoard(board, row, col);
}
}
void PlayerMove(char board[ROW][COL], int row, int col, int* count, int* copy)
{
printf("\n");
printf("玩家回合\n");
while (1)
{
int r = 0;
int c = 0;
printf("输入坐标\n");
scanf("%d %d", &r, &c);
//判断坐标合法
if (r-1 >= row || r-1 < 0 || c - 1 >= col || c - 1 < 0 || board[r - 1][c - 1] != ' ')
{
printf("错误\n");
continue;
}
//保存下棋的位置
copy[0] = r - 1 ;
copy[1] = c - 1 ;
board[r-1][c-1] = '*';
(*count)++;
return;
}
}
void ComputerMove(char board[ROW][COL], int row, int col, int* count, int* copy)
{
printf("\n");
printf("电脑回合\n");
int r, c;
while (1)
{
while (1)
{
r = rand() % 3;
//判断坐标合法
if (r < row && r >= 0)
{
break;
}
}
while (1)
{
c = rand() % 3;
//判断坐标合法
if (c < col && c >= 0)
{
break;
}
}
//判断坐标合法
if (board[r][c] == ' ')
{
//保存下棋的位置
copy[0] = r;
copy[1] = c;
board[r][c] = '#';
(*count)++;
return;
}
}
}
char Win(char board[ROW][COL], int row, int col, int* copy)
{
int wincount = 0;
//判断列
//每列的起始位置
int row_begin = copy[0] - (WIN - 1);
//每列的结束位置
int row_end = copy[0];
//row_begin至row_end每个做头
for (; row_begin != row_end; row_begin++)
{
//判断row_begin是否越界
if (row_begin >= 0)
{
//row_begin
for (int r = 0; r < WIN; r++)
{
if (row_begin+r >= ROW)
break;
if (board[row_begin+r][copy[1]] != board[copy[0]][copy[1]])
break;
else
wincount++;
}
if (wincount == WIN)
{
return board[copy[0]][copy[1]];
}
wincount = 0;
}
}
//判断行
wincount = 0;
//每行的起始位置
int col_begin = copy[1] - (WIN - 1);
//每列的结束位置
int col_end = copy[1];
//col_begin至col_end每个做头
for (; col_begin != col_end; col_begin++)
{
//判断col_begin是否越界
if (col_begin >= 0)
{
for (int c = 0; c < WIN; c++)
{
//判断col_begin是否越界
if (col_begin+c >= COL)
break;
if (board[copy[0]][col_begin+c] != board[copy[0]][copy[1]])
break;
else
wincount++;
}
if (wincount == WIN)
{
return board[copy[0]][copy[1]];
}
wincount = 0;
}
}
//判断左斜线
wincount = 0;
//每列的起始位置
row_begin = copy[0] - (WIN - 1);
//每列的结束位置
row_end = copy[0];
//每行的起始位置
col_begin = copy[1] - (WIN - 1);
//每列的结束位置
col_end = copy[1];
//board[row_begin][col_begin]至board[row_end][col_end]每个做头
for (; row_begin != row_end && col_begin != col_end; row_begin++, col_begin++)
{
//判断row_begin col_begin是否越界
if ((row_begin >= 0) && (col_begin >= 0))
{
for (int count = 0; count < WIN; count++)
{
//判断board[row_begin][col_begin]是否越界
if (row_begin+count>=ROW || col_begin+count>=COL)
break;
if (board[row_begin+count][col_begin+count] != board[copy[0]][copy[1]])
break;
else
wincount++;
}
if (wincount == WIN)
{
return board[copy[0]][copy[1]];
}
wincount = 0;
}
}
//判断右斜线
wincount = 0;
//每列的起始位置
row_begin = copy[0] - (WIN - 1);
//每列的结束位置
row_end = copy[0];
//每行的起始位置
col_begin = copy[1] + (WIN - 1);
//每列的结束位置
col_end = copy[1];
//board[row_begin][col_begin]至board[row_end][col_end]每个做头
for (; row_begin != row_end && col_begin != col_end; row_begin--, col_begin--)
{
//判断row_begin col_begin是否越界
if ((row_begin >= 0) && (col_begin < COL))
{
for (int count = 0; count < WIN; count++)
{
//判断board[row_begin][col_begin]是否越界
if (row_begin+count>=ROW || col_begin-count<0)
break;
if (board[row_begin+count][col_begin-count] != board[copy[0]][copy[1]])
break;
else
wincount++;
}
if (wincount == WIN)
{
return board[copy[0]][copy[1]];
}
wincount = 0;
}
}
return;
}
game.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 5
#define COL 5
#define WIN 3
void InitBoard(char board[ROW][COL], int row, int col);
void PrintBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col,int* count ,int* copy);
void ComputerMove(char board[ROW][COL], int row, int col , int* count ,int* copy);
char Win(char board[ROW][COL], int row, int col, int* copy);