我与C语言的点滴(8)-三子棋游戏

在设计游戏之前,自己对游戏的逻辑和步骤要非常清楚,这一点是非常重要的。
三子棋游戏它的逻辑也并不是很难。
电脑与玩家下棋,假设电脑先落子,玩家后落子,如此交替进行。直到有一方在行、列、左对角线、右对角线,四个方向的其中一种落子先满,这一方获胜。若棋盘已满却并未有以上情况,则视为平局。
在设计程序之初,首先要有菜单供玩家选择:选择开始游戏或退出游戏。此处菜单设定:1为开始游戏,0为退出游戏。假设玩家选择1,开始游戏。
首先要给出棋盘,然后电脑落子,(为了显示结果此处打印棋盘),之后玩家落子,(打印棋盘),最后判断输赢。
若未出现输赢结果,电脑再次落子,玩家也落子,如此循环。
假如棋盘已满却未论出输赢,则视为平局。
电脑落子此处设定为生成随机坐标,玩家落子需要玩家输入落子坐标。
若玩家输入非法坐标,此处最好设置提醒,保证游戏正常进行。

实现如下:
头文件game.h

#ifndef __GAME_H__
#define __GAME_H__

#define _CRT_SECURE_NO_WARNINGS 0

# include <stdio.h>
# include <stdlib.h>
# include <time.h>

#define ROW 3     //棋盘的行数
#define COL 3     //棋盘的列数

void init_board(char board[ROW][COL], int row, int col);       //棋盘的初始化
void display_board(char board[ROW][COL], int row, int col);    //打印棋盘

void computer_move(char board[ROW][COL], int row, int col);   //电脑走
void player_move(char board[ROW][COL], int row, int col);    //玩家走

int is_full(char board[ROW][COL], int row, int col);         //判断棋盘是否落满
char is_win(char board[ROW][COL], int row, int col);         //判断输赢

#endif // __GAME_H__

test.c文件


#include "game.h"

//定义游戏菜单
void menu()
{
	printf("****************************************\n");
	printf("***************1.开始游戏***************\n");
	printf("***************0.退出游戏***************\n");
	printf("****************************************\n");
}

void game()
{
	char board[ROW][COL] = {0};
	char ret = '0';
	init_board(board, ROW, COL);     //棋盘的初始化
	display_board(board, ROW, COL);  //打印棋盘

	do
	{
	    printf("电脑走:\n");
		computer_move(board, ROW, COL);     //电脑走一步
		display_board(board, ROW, COL);     //电脑走完后立即打印
		if (ret = is_win(board, ROW, COL) != ' ')
		{
			break;
		}
		printf("玩家走:\n");
		player_move(board, ROW, COL);       //玩家走一步
		display_board(board, ROW, COL);     //玩家走完后立即打印
		ret = is_win(board, ROW, COL);       //判断输赢
	} while (ret == ' ');        //返回若为空,则游戏继续,循环。

	if (is_win(board, ROW, COL) == 'Q')        //返回Q,平局。
	{
		printf("平局\n");
	}
	else  if (is_win(board, ROW, COL) == 'X')  //返回X,玩家赢。
	{
		printf("玩家赢\n");
	}
	else if (is_win(board, ROW, COL) == '*')   //返回*,电脑赢。
	{
		printf("电脑赢\n");
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	system("pause");
	return 0;
}

游戏执行文件game.c


# include "game.h"

//初始化棋盘
void init_board(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 display_board(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i<row; i++)
	{
		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		if (i != row - 1)
		{
			printf("---|---|---\n");
		}
	}
}
//电脑走
void computer_move(char board[ROW][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % row;     //随机产生电脑落子坐标
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '*';    //电脑落子
			break;
		}

	}
}
//玩家走
void player_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入落子坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) 
			//对玩家来说棋盘的第一行即为1,编程语言里棋盘的第一行为0
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = 'X';   //玩家落子
				break;
			}
			else
				printf("坐标被占用,请重新输入\n");
		}
		else
			printf("坐标不合法,请重新输入\n");
	}
}
//判断棋盘是否落满
//棋盘无空位,满。
int is_full(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;
}
//判断输赢        规则:行、列、左对角线、右对角线,四个方向落子先满的一方获胜
     //返回Q,平局。
     //返回X,玩家赢。
     //返回*,电脑赢。
char is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 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][0];
	}
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')    //三列的其中一列排满
			return board[0][j];
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')        //左对角线排满
		return board[1][1];
	else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')   //右对角线排满
		return board[1][1];

	//判断棋盘是否落满
	if (is_full(board, row, col))
		return 'Q';               //棋盘落满,则为平局。
	else
		return ' ';
}

试运行一下:
我与C语言的点滴(8)-三子棋游戏
我与C语言的点滴(8)-三子棋游戏
其实这个游戏还是可以继续扩展的,玩家选择开始游戏后,还可以设置游戏难度供玩家选择。容我再想想。