1.整体思路
(1)棋盘的样式
这就是棋盘进行初始化以及初始打印后的成果,我们要围绕这个图进行分析与讨论。
(2)棋盘的初始化
可以看到,三子棋的棋盘是三行三列,这不难想到我们应该要用到一个二维数组去初始化 ,当棋盘是空的时候我们可以将数组元素设置为空格。这就可以推断出我们应该用一个char类型的二维数组去存储九宫格的元素。我们初始化的部分就是标为1的地方,我只是为了方便我把它标为1,其实初始化的为空格。
初始化代码:
#define ROW 3 //行的宏定义,方便代码的维护
#define COL 3 //列的宏定义,方便代码的维护
void Initboard(char board[ROW][COL], int m, int n);//初始化的定义
//初始化的实现
void Initboard(char board[ROW][COL], int m, int n)
{
int i = 0;
for (i = 0; i < m; i++)
{
int j = 0;
for (j = 0; j < n; j++)
{
board[i][j] = ' ';
}
}
}
3.棋盘的打印
要如何打印这个棋盘呢?其实非常简单,只用两个循环就能做到。直接上代码:
void Displayboard(char board[ROW][COL], int m, int n);//生成棋盘
void Displayboard(char board[ROW][COL], int m, int n)
{
int i = 0;
for (i = 0; i < m; i++)
{
int j = 0;
for (j = 0; j < n; j++)
{
printf(" %c ", board[i][j]);
if (j < n - 1)
printf("|");
}
printf("\n");
if (i < m - 1)
{
for (j = 0; j < n; j++)
{
printf("---");
if (j < n - 1)
printf("|");
}
}
printf("\n");
}
}
4.玩家下棋
因为作者水平有限不能做到用鼠标点来下棋,所以只能用坐标的形式去进行下棋。一共三行三列,所以进行的就是1 1,1 2,1 3,2 1……的形式来进行下棋。如果超出范围就会提示超出边界,如果玩家下的地方已经落子也会提示该区域已经有了棋子。
玩家的下的棋子我设置为 * 让棋盘更加真实。上代码
void PlayerMove(char board[ROW][COL], int m, int n);//声明
//实现
void PlayerMove(char board[ROW][COL], int m, int n)
{
printf("It is time for you to play chess!\n");
while (1)
{
printf("Please enter the coordinates!\n");
int x, y;
scanf("%d%d", &x, &y);//输入坐标
if (x > m || y > n)//判断是否超过边界
{
printf("Beyond the boundary,please re-enter!--->");;
}
if (board[x - 1][y - 1] != ' ')//判断下棋点是否为空
{
printf("\n");
printf("This grid is already in use, please re-enter!--->");
}
else
{
board[x - 1][y - 1] = '*';
break;
}
}
}
5.电脑下棋
电脑下棋的坐标是随机生成的,我们使用的是定义一个x坐标,一个y坐标,然后使用rand()函数进行生成随机数。然后用时间戳然随机生成的数更加随机。即在主函数前定义一下该函数的使用srand((unsigned)time(NULL));
rand和srand函数的头文件是#include<stdlib.h>
time函数的头文件是#include<time.h> 上代码:
void ComputerMove(char board[ROW][COL], int m, int n);//声明
void ComputerMove(char board[ROW][COL], int m, int n)
{
printf("This computer play!\n");
int x, y;
while (1)
{
x = rand() % m;
y = rand() % n;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
6.输赢的判断
1.输赢判断的标准
(1).玩家赢我们返回一个 *
(2).电脑赢我们返回一个 #
(3)平局我们返回一个 Q
(4)游戏继续我们就返回一个 C
在主函数上的代码为:
void game()
{
char board[ROW][COL];//棋盘
//初始化棋盘
Initboard(board, ROW, COL);
Displayboard(board, ROW, COL);
char ret = 0;
while (1)
{
PlayerMove(board, ROW, COL);
Displayboard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
ComputerMove(board, ROW, COL);
Displayboard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("player win!!\n");
else if (ret == '#')
printf("computet win!\n");
else
printf("Tie game\n");
}
那么如何去实现这个赢的逻辑呢?我们可以分为如下几点进行判断:
(1).横向三个连子赢
(2).纵向三个连字赢
(3).向下对角线赢
(4).向上对角线赢
char IsWin(char board[ROW][COL], int m, int n);//声明
char IsWin(char board[ROW][COL], int m, int n)
{
//1.判断输赢
//(1).横向赢
int i, j;
for (i = 0; i < m; i++)
{
int count1 = 0;
int count2 = 0;
for (j = 0; j < n; j++)
{
if (board[i][j] == '*')
count1++;
if (board[i][j] == '#')
count2++;
}
if (count1 == n)
return '*';
if (count2 == n)
return '#';
}
//(2).竖向赢
for (i = 0; i < n; i++)
{
int count1 = 0;
int count2 = 0;
for (j = 0; j < m; j++)
{
if (board[j][i] == '*')
count1++;
if (board[j][i] == '#')
count2++;
}
if (count1 == m)
return '*';
if (count2 == m)
return '#';
}
//(3).下对角线赢
int x = 0, y = 0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (i == j && board[i][j] == '*')
x++;
if (i == j && board[i][j] == '#')
y++;
}
}
if (x == 3)
return '*';
if (y == 3)
return '#';
//(4).上对角线赢
j = n - 1;
int countone = 0;
int counttwo = 0;
for (i = 0; i < m; i++)
{
if (board[i][j] == '*')
countone++;
if (board[i][j] == '#')
counttwo++;
if (countone == m)
return '*';
if (counttwo == m)
return '*';
j--;
}
//2.判断平局
int count = m * n;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
if (board[i][j] == ' ')
count--;
}
if (count == 9)
{
return 'Q';
}
//3.游戏继续
return 'C';
}
7.完整代码
1.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("****************************************\n");
printf("************* 1.play ***************\n");
printf("************* 0.exit ***************\n");
printf("****************************************\n");
}
void game()
{
char board[ROW][COL];//棋盘
//初始化棋盘
Initboard(board, ROW, COL);
Displayboard(board, ROW, COL);
char ret = 0;
while (1)
{
PlayerMove(board, ROW, COL);
Displayboard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
ComputerMove(board, ROW, COL);
Displayboard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("player win!!\n");
else if (ret == '#')
printf("computet win!\n");
else
printf("Tie game\n");
}
int main()
{
int input;
srand((unsigned int)time(NULL));
do
{
menu();
printf("please select:>");
scanf("%d", &input);
switch (input)
{
case 0:
printf("exit successful!\n");
break;
case 1:
game();
break;
default:
printf("Select error! Please select again\n");
break;
}
} while (input);
return 0;
}
2.game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void Initboard(char board[ROW][COL], int m, int n)
{
int i = 0;
for (i = 0; i < m; i++)
{
int j = 0;
for (j = 0; j < n; j++)
{
board[i][j] = ' ';
}
}
}
void Displayboard(char board[ROW][COL], int m, int n)
{
int i = 0;
for (i = 0; i < m; i++)
{
int j = 0;
for (j = 0; j < n; j++)
{
printf(" %c ", board[i][j]);
if (j < n - 1)
printf("|");
}
printf("\n");
if (i < m - 1)
{
for (j = 0; j < n; j++)
{
printf("---");
if (j < n - 1)
printf("|");
}
}
printf("\n");
}
}
void PlayerMove(char board[ROW][COL], int m, int n)
{
printf("It is time for you to play chess!\n");
while (1)
{
printf("Please enter the coordinates!\n");
int x, y;
scanf("%d%d", &x, &y);
if (x > m || y > n)
{
printf("Beyond the boundary,please re-enter!--->");;
}
if (board[x - 1][y - 1] != ' ')
{
printf("\n");
printf("This grid is already in use, please re-enter!--->");
}
else
{
board[x - 1][y - 1] = '*';
break;
}
}
}
void ComputerMove(char board[ROW][COL], int m, int n)
{
printf("This computer play!\n");
int x, y;
while (1)
{
x = rand() % m;
y = rand() % n;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//玩家赢返回 '*'
//电脑赢返回 '#'
//平局返回 'Q'
//游戏继续 'C'
char IsWin(char board[ROW][COL], int m, int n)
{
//1.判断输赢
//(1).横向赢
int i, j;
for (i = 0; i < m; i++)
{
int count1 = 0;
int count2 = 0;
for (j = 0; j < n; j++)
{
if (board[i][j] == '*')
count1++;
if (board[i][j] == '#')
count2++;
}
if (count1 == n)
return '*';
if (count2 == n)
return '#';
}
//(2).竖向赢
for (i = 0; i < n; i++)
{
int count1 = 0;
int count2 = 0;
for (j = 0; j < m; j++)
{
if (board[j][i] == '*')
count1++;
if (board[j][i] == '#')
count2++;
}
if (count1 == m)
return '*';
if (count2 == m)
return '#';
}
//(3).下对角线赢
int x = 0, y = 0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (i == j && board[i][j] == '*')
x++;
if (i == j && board[i][j] == '#')
y++;
}
}
if (x == 3)
return '*';
if (y == 3)
return '#';
//(4).上对角线赢
j = n - 1;
int countone = 0;
int counttwo = 0;
for (i = 0; i < m; i++)
{
if (board[i][j] == '*')
countone++;
if (board[i][j] == '#')
counttwo++;
if (countone == m)
return '*';
if (counttwo == m)
return '*';
j--;
}
//2.判断平局
int count = m * n;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
if (board[i][j] == ' ')
count--;
}
if (count == 9)
{
return 'Q';
}
//3.游戏继续
return 'C';
}
3.game.h
#pragma once
#define ROW 3
#define COL 3
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
//棋盘的初始化
void Initboard(char board[ROW][COL], int m, int n);
//棋盘的打印生成
void Displayboard(char board[ROW][COL], int m, int n);
//玩家走
void PlayerMove(char board[ROW][COL], int m, int n);
//电脑走
void ComputerMove(char board[ROW][COL], int m, int n);
//判断输赢以及是否继续
char IsWin(char board[ROW][COL], int m, int n);
8.演示效果