概述
将下三子棋的过程分成几个步骤(1.初始化空格2.显示棋盘3.玩家下4.电脑下5.判断结果6.整合),利用不同的函数实现每个步骤,同时采用多文件让整个程序更清晰明了(头文件、函数文件和主函数文件)
代码Part
part 1 chess.h
#ifndef _CHESS_H_
#define _CHESS_H
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#pragma warning(disable:4996)
#define ROW 3
#define COL 3
#define BLACK_PIECE 'X'
#define WHITE_PIECE 'O'
void Game();
void InitBoard(char board[][COL], int row, int col);
void ShowBoard(char board[][COL], int row, int col);
int PlayerMove(char board[][COL], int row, int col);
void ComputerMove(char board[][COL], int row, int col);
char JudgeResult(char board[][COL], int row, int col);
#endif
头文件部分宏定义了行和列,三子棋当然是三行三列了,之所以用宏定义也是为了方便后续修改个数时使用该程序更方便。另外宏定义了黑子和白子,黑子用X,白子用O,当然也可以用其他的。之后就是函数框架了,首先声明Game(),然后初始化空格Initboard(),之后是显示棋盘Showboard(),玩家下PlayerMove(),电脑下ComputerMove(),最后判断输赢JudgeResult()。
part 2 main.c
主函数部分的头文件用第一部分的就行
#include"chess.h"
这一部分需要声明一个菜单函数让玩家做出选择玩还是结束,然后就是一把玩完后是否再玩下一把,这也是这个游戏的整体框架,代码如下:
void Menu(){
printf("########################\n");
printf("##欢迎来到三子棋游戏####\n");
printf("########################\n");
printf("#1.Play 2.Exit####\n");
printf("########################\n");
printf("Please Enter Select:>");
}
int main(){
int quit = 0;
while (!quit){
int select = 0;
Menu();
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 2:
quit = 1;
break;
default:
printf("Enter Error\n");
break;
}
}
system("pause");
return 0;
}
part 3 chess.c
这一部分也是要头文件的,同上
#include "chess.h"
这个模块是函数部分,就是将第一部分的各个函数写出来:
InitBoard()
初始化空格可以用二维数组的初始化来实现,定义一个三行三列的数组,利用两个for循环把空格赋给每个元素就好啦,下面就是代码:
void InitBoard(char board[][COL], int row, int col)
{
int i = 0;
for (; i < row; i++)
{
int j = 0;
for (; j < col; j++)
{
board[i][j] = ' ';
}
}
}
Showboard()
显示棋盘部分我们可以先想象一下棋盘上面第一行先标出来1,2,3(中间用“|”隔开)对应每列,行与行之间打印出来一行虚线作为界限,之后的每一行可以用一个for循环先打印一个行序号再打印每个数组元素,数组元素间用“|”分开,更加清晰,如果不确定空格或者虚线的个数,可以先运行出来看看效果再做修改。代码如下:
void ShowBoard(char board[][COL], int row, int col)
{
printf(" | 1 | 2 | 3 |\n");
int i = 0;
for (; i < row; i++){
printf("----------------\n");
printf(" %d | %c | %c | %c |\n", i + 1, board[i][0], board[i][1], board[i][2]);
}
printf("----------------\n");
}
PlayerMove()
下面玩家就开始下子,首先玩家要输入他的位置,然后判断这个位置是否在九个数组元素之内并且是否为空格,如果是的,就把这个空格落上子(玩家的子用X表示),如果不是空格提示他输入错误,请重新输入。代码如下:
int PlayerMove(char board[][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("Please Enter Your Pos<x, y># ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 3 && y >= 1 && y <= 3){
if (board[x - 1][y - 1] != ' '){
return 2;
}
board[x - 1][y - 1] = BLACK_PIECE;
return 0;
}
return 1; //用户输入坐标有误
}
ComputerMove()
玩家下完就该电脑下了,电脑下子是随机的可以采用rand函数实现,为了让子落在空格也要用到刚才的判定条件。代码如下:
void ComputerMove(char board[][COL], int row, int col){
while (1){
int i = rand() % row;
int j = rand() % col;
if (board[i][j] ==' '){
board[i][j] = WHITE_PIECE;
break;
}
}
printf("computer ...done\n");
Sleep(1000);
}
JudgeResult()
双方都落完子就可以判断输赢了,判断每一行或每一列或者两条对角线上的元素不为空且相等就可以返回其中任意一个数组元素,代表他赢了;如果没有玩家获胜就判断棋盘上是否有空格,如果有空格返回N游戏继续,没有空格则返回E表示平局,代码如下:
char JudgeResult(char board[][COL], int row, int col)
{
int i = 0;
for (; i < row; i++){
if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][1] == board[i][2]){
return board[i][0];
}
}
for (i = 0; i < col; i++){
if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[1][i] == board[2][i]){
return board[0][i];
}
}
if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[1][1] == board[2][2]){
return board[0][0];
}
if (board[0][2] != ' ' && board[0][2] == board[1][1] && board[1][1] == board[2][0]){
return board[1][1];
}
for (i = 0; i < row; i++){
int j = 0;
for (; j < col; j++){
if (board[i][j] == ' '){
return 'N';
}
}
}
return 'E';
}
Game()
以上各个函数的铺垫都是为了之最重要的一步,这个函数是把前面的各个函数做了一个整合,将各个函数按照顺序执行一遍,并将每个返回值对应的什么结果打印出来,代码如下:
void Game(){
char board[ROW][COL];
InitBoard(board, ROW, COL);
char result = 'N';
srand((unsigned long)time(NULL));
while (1){
ShowBoard(board, ROW, COL);
int type = PlayerMove(board, ROW, COL);
if (1 == type){
printf("你输入的坐标有误,请重新输入!\n");
continue;
}
else if (2 == type){
printf("你输入的坐标已经被占用,请重新输入!\n");
continue;
}
else{
printf("Player ..Done!\n");
}
result = JudgeResult(board, ROW, COL);
if (result != 'N'){
break;
}
ComputerMove(board, ROW, COL);
result = JudgeResult(board, ROW, COL);
if (result != 'N'){
break;
}
}
ShowBoard(board, ROW, COL);
switch (result){
case 'E':
printf("平局\n");
break;
case BLACK_PIECE:
printf("你赢了\n");
case WHITE_PIECE:
printf("电脑赢了\n");
break;
}
}
需要注意的是函数中有一个“srand((unsigned long)time(NULL));”这个函数常与rand函数一起使用,从而得到一个随机值。
总结
三子棋这个程序整体看来其实并不是很难,分成各个函数化繁为简逻辑就很清晰了,这篇博客也算是我真正意义上的第一篇博客,如有不妥之处,请指正。