前言
本章为综合练习(函数与数组综合运用) —— “三子棋”
本次练习采用分模块进行开发
分为三个部分:
- ThreeSonChessGame.h:进行一些头文件的包含和函数的声明
- ThreeSonChessGame.c:函数功能的实现
- ThreeSonChessPlay.c:游戏的主逻辑
ThreeSonChessGame.h 头文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
// 头文件的包含
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 定义标识符常量
#define ROW 3
#define COL 3
// 函数的声明
// 初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
// 打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
// 电脑下棋
void RobotMove(char board[ROW][COL], int row, int col);
// 获胜
// 1、玩家赢了 - *
// 2、电脑赢了 - #
// 3、平局 - Q
// 4、游戏继续 - C
char IsWin(char board[ROW][COL], int row, int col);
// 平局
int IsFull(char board[ROW][COL], int row, int col);
ThreeSonChessGame.c 函数实现文件
#pragma once
#include "ThreeSonChessGame.h"
// 函数的实现
// 初始化棋盘实现
void InitThreeSonChessBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
// 打印棋盘的实现
void DisplayThreeSonChessBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
// 玩家下棋的实现
void PlayerMove(char board[ROW][COL], int row, int col)
{
while (1)
{
// 判断坐标合法性
int x = 0;
int y = 0;
printf("玩家走-请输入坐标:>\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
// 下棋
// 坐标是否被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
// 电脑下棋的实现
void RobotMove(char board[ROW][COL], int row, int col)
{
printf("电脑走-请输入坐标:>\n");
while (1)
{
// 生成0~2之间的坐标
int x = rand() % row;
int y = rand() % col;
// 下棋
// 坐标是否被占用
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
// 棋盘满了则平局
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0; // 棋盘未满
}
}
}
return 1; // 棋盘满了
}
// 获胜的实现
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
// 判断三行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
// 判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
// 判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
// 平局
int result = IsFull(board, row, col);
if (result)
{
printf("平 %d\n", result);
return 'Q';
}
return 'C';
}
ThreeSonChessPlay.c 游戏主逻辑文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "ThreeSonChessGame.h"
void ThreeSonChessMenu()
{
printf("\n");
printf("*******************************************\n");
printf("************* 1. play *************\n");
printf("************* 0. exit *************\n");
printf("*******************************************\n");
}
void ThreeSonChessGame()
{
// 存储数据 - 二维数组
char board[ROW][COL];
// 初始化棋盘 - 初始化空格
InitThreeSonChessBoard(board, ROW, COL);
// 打印棋盘 - 本质打印数组
DisplayThreeSonChessBoard(board, ROW, COL);
// 初始化获胜值
char result = 0;
while (1)
{
// 玩家下棋
PlayerMove(board, ROW, COL);
DisplayThreeSonChessBoard(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result != 'C')
{
break;
}
// 电脑下棋
RobotMove(board, ROW, COL);
DisplayThreeSonChessBoard(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result != 'C')
{
break;
}
}
switch (result)
{
case '*':
printf("\n");
printf("玩家获胜\n");
break;
case '#':
printf("\n");
printf("电脑获胜\n");
break;
case 'Q':
printf("\n");
printf("游戏平局\n");
break;
}
DisplayThreeSonChessBoard(board, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
ThreeSonChessMenu();
printf("请选择:> ");
scanf("%d", &input);
switch (input)
{
case 1:
ThreeSonChessGame();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
srand((unsigned int)time(NULL))的理解
有点小伙伴可能会对这行代码产生疑问?这句话到底是什么意思呢?
这句话的作用是根据时间戳设置随机数种子
首先我们需要明白下面两者的作用:
- srand与rand的关系:
- 在C语言中srand函数经常跟rand函数一起使用,srand是随机数发生器的初始化函数,这两个函数都位与<stdlib.h>头文件里面
- rand函数每一次被调用的时候,它都会查看之前是否调用了srand函数
- 如果调用了,则会调用srand(seed)来初始化它的随机值
- 如果没有调用,则会默认的调用srand(1)来初始化它的随机值
- rand()函数产生的随机数范围为0-0x7fff,即0-32767
- time的作用:
- time函数可以获取当前的系统时间(但获取的是秒数,是从1970年1月1日零时零分零秒到目前为止所经过的时间),time可以将其转化为常规的时间
- 当srand()的参数值固定的时候,rand()获得的数也是固定的,所以一般srand的参数用time(NULL),因为系统的时间一直在变,所以rand()获得的数,也就一直在变,相当于是随机数了
- 若想在一个程序中生成随机数,只需在主程序开始处调用srand((unsigned int)time(NULL)),后面直接用rand()就可以了