0
点赞
收藏
分享

微信扫一扫

Linux tar解压指令

目录

前言

一、游戏规则

1.功能分析

2.玩法分析

3.胜负判定条件

二、游戏实现思路

三、代码实现与函数封装

1.项目文件创建

2.头文件说明

3.函数封装 

1)菜单实现

 2)进度条实现

 3)main函数实现

 4)Game函数

 5)ShowBoard函数实现

6)PlayerMove函数实现

7)ChessCount函数实现

 8)IsOver函数实现

四、源码分享

1.main.c

2.ProBar.h

 3.probar.c

4.game.h

5.game.c

总结


前言

五子棋,又称连珠棋,是一种双人对弈的棋类游戏。游戏目标是在一个棋盘上,通过在横、竖、斜线上依次放置棋子,使自己的五个棋子连成一线,即横线、竖线或斜线,且无被对手堵住的空位,从而获胜。

实现简单的五子棋游戏,需要有二维数组函数调用等知识。本项目代码量大致为两三百行。

一、游戏规则

1.功能分析

五子棋的功能比较简单,只有黑棋落子和白棋落子,有些五子棋还有悔棋功能、显示胜率、记录走的步数等功能,但是初学时可以只实现简单的落子功能即可。

2.玩法分析

由黑棋先走,鼠标左击即可落子,然后轮到白棋回合,如此循环直到游戏结束。

3.胜负判定条件

五子棋的棋盘通常为15×15的格子,双方轮流在空位上放置自己的棋子,先连成五子的一方获胜。如果棋盘填满但没有五子连成一线,游戏结束为平局。

二、游戏实现思路

  1. 使用坐标输入代替鼠标点击,坐标应该符合人们使用习惯从1开始;(【鼠标左击】功能)
  2. 若有人胜利提示胜利方为谁,并结束游戏;
  3. 若无人胜利,且棋盘未满,提示继续;
  4. 若棋盘已满,提示平局;
  5. 实现清屏功能,每次落完子之后刷新屏幕;
  6. 可以加入进度条,在游戏开始时展示。

三、代码实现与函数封装

1.项目文件创建

将源代码分为五个文件,两个头文件(.h),用于声明函数,分别声明进度条和游戏函数;

三个源文件(.c),两个用于写函数体,实现进度条和游戏主体,一个为主函数,调用函数。

2.头文件说明

1.为了防止在项目中多次申明同一个头文件,需要加入防重复判断语句

#pragma once

2.头文件中可以直接引用需要的标准库,然后在源文件中只需要引用自己写的头文件即可;

#include "game.h"
#include "ProBar.h"

3.函数封装 

棋盘设置为15×15,且可更改方便之后的更改。

1)菜单实现

void Menu()
{
	printf("#########################\n");
	printf("### 1.Play     0.Exit ###\n");
	printf("#########################\n");
	printf("Please Select:> ");
}

 2)进度条实现

'\r'使光标每次回到开头的位置,使用fflush函数刷新输出界面,并使用usleep函数进行延迟,达到很好的效果。

#define NUM 100

void  process_bar()
{
	char bar[NUM+1];
	memset(bar, '\0', sizeof(bar));
	
	const char* lable = "|/-\\";
	int i = 0;
	while(i <= NUM)
	{
		printf("Load...[%-100s][%-3d%%][%c]\r", bar, i, lable[i%4]);
		fflush(stdout);
		bar[i++] = '#';
		usleep(10000);
	}
	printf("\n");
}

 3)main函数实现

使用quit变量来控制循环的退出;

Game函数实现游戏的主体。

int main()
{
	int quit = 0;

	int select = 0;
	while(!quit)
	{
						
		Menu();
		scanf("%d", &select);
		switch(select)
		{
			case 1:
				process_bar();
				Game();
				break;
			case 0:
				quit = 1;
				printf("Exit Success!\n");
				break;
			defualt :
				printf("Enter Error, Try Again!\n");
				break;
		}
	}
	

	return 0;
}

 4)Game函数

  1. 建立棋盘
  2. 使用memset函数初始化棋盘;
  3. do...while执行游戏运行;
  4. IsOver函数判断游戏是否结束;
  5. PlayerMove函数玩家走一步棋;
  6. Showboard 打印出棋盘;
  7. switch...case 显示出游戏结果。
#define ROW 20
#define COL 20

#define PLAYER1 1
#define PLAYER2 2

#define NEXT 0
#define PLAYER1_WIN 1
#define PLAYER2_WIN 2
#define DRAW		3


void Game()
{
	int board[ROW][COL];
	memset(board, '\0', sizeof(board));
	int result = NEXT;
	do
	{
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL, PLAYER1);
		result = IsOver(board, ROW, COL);
		if(NEXT != result)
		{
			break;
		}
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL, PLAYER2);

		result = IsOver(board, ROW, COL);
		if(NEXT != result)
		{
			break;
		}
	}while(1);
	//p1 win , p2 win, draw
	ShowBoard(board, ROW, COL);
	switch(result)
	{
		case PLAYER1_WIN:
			printf("congratulate Player1, you win!\n");
			break;
		case PLAYER2_WIN:
			printf("congratulate player2, you win!\n");
			break;
		case DRAW:
			printf("draw!\n");
			break;
		default:

			break;
	}
}

 5)ShowBoard函数实现

刷新屏幕

void ShowBoard(int board[ROW][COL], int row, int col)
{
	//clear screen
	//printf("\e[1;1H\e[2J")"]]");

	//printf("  ");

	printf("\033c");
	printf("\n\n  ");
	for(int i=0; i<col; i++)
	{
		printf("%3d", i+1);
	}
	printf("\n");

	for(int i=0; i<row; i++)
	{
		printf("%2d ", i+1);
		for(int j=0; j<col; j++)
		{
			if(board[i][j] == 0)
			{
				printf(" . ");
			}
			else if(board[i][j] == PLAYER1)
			{
				printf(" x ");
			}
			else
			{
				printf(" o ");
			}
		}
		printf("\n");
	}
}

6)PlayerMove函数实现

int x = 0;
int y = 0;

void PlayerMove(int board[ROW][COL], int row, int col, int player)
{
	while(1)
	{
		printf("\nPlayer[%d] Please Enter Your Pos:>", player);
		scanf("%d %d", &x, &y);
        //判断合法坐标
		if(x<1 || x> row || y<1 || y>col)
		{
			printf("Pos is not right!\n");
			continue;
		}
		else if(board[x-1][y-1] != 0)
		{
			printf("Pos is occpuied!\n");
			continue;
		}
		else{
			board[x-1][y-1] = player;//谁落子,就放置谁的数据

			break;
		}

	}
}

7)ChessCount函数实现

要判断是否继续下棋需要判断是否已经五子连珠,就需要数下的这个子周围有没有出现五子连珠,由于每次下棋都会判断一次,所以不会出现漏判的情况。

enum Dir
{
	LEFT,
	RIGHT,
	UP,
	DOWN,
	LEFT_UP,
	LEFT_DOWN,
	RIGHT_UP,
	RIGHT_DOWN
};

int ChessCount(int board[ROW][COL], int row, int col, enum Dir d)
{
	int _x = x-1;
	int _y = y-1;
	
	int count = 0;

	while(1)
	{
		switch(d)
		{
			case LEFT:
				_y--;
				break;
			case RIGHT:
				_y++;
				break;
			case UP:
				_x--;
				break;
			case DOWN:
				_x++;
				break;
			case LEFT_UP:
				_x--;
				_y--;
				break;
			case LEFT_DOWN:
				_x++;
				_y--;
				break;
			case RIGHT_UP:
				_x--, _y++;
				break;
			case RIGHT_DOWN:
				_x++, _y++;
				break;
			default:
				//Do nothing
				break;

		}
		if(_x<0 || _x>row-1 || _y<0 || _y > col-1)
		{
			break;
		}

		if(board[x-1][y-1] == board[_x][_y])
		{
			count++;
		}
		else
		{
			break;
		}
	}
	return count;
}

 8)IsOver函数实现

任何落子位置都有八个方向,所以判定五子连珠,本质是判定1,5方向之和,2,6方向之和,3,7方向之和,4,8方向 之和,其中任意一个出现相同的连续五个棋子,即游戏结束

int IsOver(int board[ROW][COL], int row, int col)
{
    //注意,每次统计的时候,都没有统计当前节点,需要单独+1
	int count1 = ChessCount(board, row, col, LEFT) +
		ChessCount(board, row, col, RIGHT) + 1;
	int count2 = ChessCount(board, row, col, UP) +
		ChessCount(board, row, col, DOWN) + 1;
	int count3 = ChessCount(board, row, col, LEFT_UP) +
		ChessCount(board, row, col, RIGHT_DOWN) + 1;
	int count4 = ChessCount(board, row, col, LEFT_DOWN) +
		ChessCount(board, row, col, RIGHT_UP) + 1;
	
	if(count1 >= 5 || count2>=5 || count3>=5 || count4>=5)
	{
        //谁赢返回谁
		//return board[x-1][y-1];
		if(board[x-1][y-1] == PLAYER1)
		{
			return PLAYER1_WIN;
		}
		else
		{
			return PLAYER2_WIN;
		}
	}

	for(int i=0; i<row; i++)
	{
		for(int j=0; j<col; j++)
		{
			if(board[i][j] == 0)
			{
                //棋盘未满,返回继续
				return NEXT;
			}
		}
	}
    //棋盘已满且没人赢,返回平局
	return DRAW;
}

四、源码分享

1.main.c

#include "game.h"
#include "ProBar.h"

int main()
{
	int quit = 0;

	int select = 0;
	while(!quit)
	{
						
		Menu();
		scanf("%d", &select);
		switch(select)
		{
			case 1:
				process_bar();
				Game();
				break;
			case 0:
				quit = 1;
				printf("Exit Success!\n");
				break;
			defualt :
				printf("Enter Error, Try Again!\n");
				break;
		}
	}
	

	return 0;
}

2.ProBar.h

#pragma once 

#include <stdio.h>
#include <unistd.h>
#include <string.h>


#define NUM 100

void process_bar();

 3.probar.c

#include "ProBar.h"

void  process_bar()
{
	char bar[NUM+1];
	memset(bar, '\0', sizeof(bar));
	
	const char* lable = "|/-\\";
	int i = 0;
	while(i <= NUM)
	{
		printf("Load...[%-100s][%-3d%%][%c]\r", bar, i, lable[i%4]);
		fflush(stdout);
		bar[i++] = '#';
		usleep(10000);
	}
	printf("\n");
}

4.game.h

#include <string.h>
#include <stdlib.h>

#define ROW 20
#define COL 20

#define PLAYER1 1
#define PLAYER2 2

#define NEXT 0
#define PLAYER1_WIN 1
#define PLAYER2_WIN 2
#define DRAW		3

enum Dir
{
	LEFT,
	RIGHT,
	UP,
	DOWN,
	LEFT_UP,
	LEFT_DOWN,
	RIGHT_UP,
	RIGHT_DOWN
};

void Menu();
void Game();

int IsOver(int board[ROW][COL], int row, int col);
void ShowBoard(int board[ROW][COL], int row, int col);
int ChessCount(int board[ROW][COL], int row, int col, enum Dir d);
void Playermove(int board[ROW][COL], int row, int col, int player);

5.game.c

#include "game.h"
#include "ProBar.h"
int x = 0;
int y = 0;

void Menu()
{
	printf("#########################\n");
	printf("### 1.Play     0.Exit ###\n");
	printf("#########################\n");
	printf("Please Select:> ");
}

//four possbilities:
//NEXT: continue
//1: 1 win
//2: 2 win
//3: draw
int IsOver(int board[ROW][COL], int row, int col)
{
	//import && hard
	//wu zi lian zhu
	int count1 = ChessCount(board, row, col, LEFT) +
		ChessCount(board, row, col, RIGHT) + 1;
	int count2 = ChessCount(board, row, col, UP) +
		ChessCount(board, row, col, DOWN) + 1;
	int count3 = ChessCount(board, row, col, LEFT_UP) +
		ChessCount(board, row, col, RIGHT_DOWN) + 1;
	int count4 = ChessCount(board, row, col, LEFT_DOWN) +
		ChessCount(board, row, col, RIGHT_UP) + 1;
	
	if(count1 >= 5 || count2>=5 || count3>=5 || count4>=5)
	{
		//return board[x-1][y-1];
		if(board[x-1][y-1] == PLAYER1)
		{
			return PLAYER1_WIN;
		}
		else
		{
			return PLAYER2_WIN;
		}
	}

	for(int i=0; i<row; i++)
	{
		for(int j=0; j<col; j++)
		{
			if(board[i][j] == 0)
			{
				return NEXT;
			}
		}
	}
	return DRAW;
}

int ChessCount(int board[ROW][COL], int row, int col, enum Dir d)
{
	int _x = x-1;
	int _y = y-1;
	
	int count = 0;

	while(1)
	{
		switch(d)
		{
			case LEFT:
				_y--;
				break;
			case RIGHT:
				_y++;
				break;
			case UP:
				_x--;
				break;
			case DOWN:
				_x++;
				break;
			case LEFT_UP:
				_x--;
				_y--;
				break;
			case LEFT_DOWN:
				_x++;
				_y--;
				break;
			case RIGHT_UP:
				_x--, _y++;
				break;
			case RIGHT_DOWN:
				_x++, _y++;
				break;
			default:
				//Do nothing
				break;

		}
		if(_x<0 || _x>row-1 || _y<0 || _y > col-1)
		{
			break;
		}

		if(board[x-1][y-1] == board[_x][_y])
		{
			count++;
		}
		else
		{
			break;
		}
	}
	return count;
}

void ShowBoard(int board[ROW][COL], int row, int col)
{
	//clear screen
	//printf("\e[1;1H\e[2J")"]]");

	//printf("  ");

	printf("\033c");
	printf("\n\n  ");
	for(int i=0; i<col; i++)
	{
		printf("%3d", i+1);
	}
	printf("\n");

	for(int i=0; i<row; i++)
	{
		printf("%2d ", i+1);
		for(int j=0; j<col; j++)
		{
			if(board[i][j] == 0)
			{
				printf(" . ");
			}
			else if(board[i][j] == PLAYER1)
			{
				printf(" x ");
			}
			else
			{
				printf(" o ");
			}
		}
		printf("\n");
	}
}

void PlayerMove(int board[ROW][COL], int row, int col, int player)
{
	while(1)
	{
		printf("\nPlayer[%d] Please Enter Your Pos:>", player);
		scanf("%d %d", &x, &y);
		if(x<1 || x> row || y<1 || y>col)
		{
			printf("Pos is not right!\n");
			continue;
		}
		else if(board[x-1][y-1] != 0)
		{
			printf("Pos is occpuied!\n");
			continue;
		}
		else{
			board[x-1][y-1] = player;
			break;
		}

	}
}

void Game()
{
	int board[ROW][COL];
	memset(board, '\0', sizeof(board));
	int result = NEXT;
	do
	{
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL, PLAYER1);
		result = IsOver(board, ROW, COL);
		if(NEXT != result)
		{
			break;
		}
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL, PLAYER2);

		result = IsOver(board, ROW, COL);
		if(NEXT != result)
		{
			break;
		}
	}while(1);
	//p1 win , p2 win, draw
	ShowBoard(board, ROW, COL);
	switch(result)
	{
		case PLAYER1_WIN:
			printf("congratulate Player1, you win!\n");
			break;
		case PLAYER2_WIN:
			printf("congratulate player2, you win!\n");
			break;
		case DRAW:
			printf("draw!\n");
			break;
		default:

			break;
	}
}

总结

实际上这个版本还是一个非常简易的版本,在之后学习到别的模块之后可以对这个项目再进行改进,比如可以尝试以下功能:

  • 人机对战
  • 功能扩展:颜色提示,步数记录,先手随机交换等
  • 网络版本

码云Gitee项目链接:GoBangGame · Kevin Ray/LinuxPractice - 码云 - 开源中国 (gitee.com)

举报

相关推荐

0 条评论