一、前言
最近在阅读《unix-linux编程实践教程》,这本书很适合学习完Linux基础编程后想码点东西实践的朋友。它主要是通过带领读者学习编写Linux系统中常用的命令(ls、more等)来巩固基础知识。本人从中收获颇丰,在这里推荐给各位想学习Linux系统编程的朋友。下载路径:https://download.csdn.net/download/q1449516487/10724621
二、掷骰子游戏
1.curses库(图形函数库)
(1)这个游戏运用到了curses库,它是一个在Linux/Unix下广泛应用的图形函数库.,作用是可以绘制在终端下的用户界面和漂亮的图形。
(2)安装方法:sudo apt-get install libncurses5-dev
(3)重要函数
函数 | 功能 |
---|---|
initscr() | 初始化curses库和ttty (在开始curses编程之前,必须使用initscr()这个函数来开启curses模式) |
endwin() | 关闭curses并重置tty (结束curses编程时,最后调用的一个函数) |
move(y,x) | 将游标移动至 x,y 的位置 |
getyx(win,y,x) | 得到目前游标的位置(请注意!是 y,x 而不是&y,&x) |
clear() and erase() | 将整个萤幕清除(请注意配合refresh() 使用) |
echochar(ch) | 显示某个字元 |
addch(ch) | 在当前位置画字符ch |
mvaddch(y,x,ch) | 在(x,y) 上显示某个字元。相当於呼叫move(y,x);addch(ch); |
addstr(str) | 在当前位置画字符串str |
mvaddstr(y,x,str) | 在(x,y) 上显示一串字串。相当於呼叫move(y,x);addstr(str); |
printw(format,str) | 类似 printf() ,以一定的格式输出至萤幕 |
mvprintw(y,x,format,str) | 在(x,y) 位置上做 printw 的工作。相当於呼叫move(y,x);printw(format,str); |
getch() | 从键盘读取一个字元。(注意!传回的是整数值) |
getstr() | 从键盘读取一串字元。 |
scanw(format,&arg1,&arg2...) | 如同 scanf,从键盘读取一串字元。 |
beep() | 发出一声哔声 |
box(win,ch1,ch2) | 自动画方框 |
refresh() | 使屏幕按照你的意图显示。比较工作屏幕和真实屏幕的差异,然后refresh通过终端驱动送出那些能使真实屏幕于工作屏幕一致的字符和控制码。(工作屏幕就像磁盘缓存,curses中的大部分的函数都只对它进行修改) |
standout() | 启动standout模式(一般使屏幕发色) |
standend() | 关闭standout模式 |
2.时间间隔器
(1)使用到时间间隔器,主要的作用是让电脑自动掷骰子。该时间间隔期的本质是一个时钟信号,我们通过设定间隔时间,内核在到达我们设定的时间时就会向进程发送一个时钟信号,进而程序调用操作函数实现功能。(信号也可以理解为我们熟悉的中断)
(2)操作函数
函数 | int getitimer(int which, struct itimerval *curr_value); | |
---|---|---|
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); | ||
变量 | which | ITIMER_REAL:这个计时器计量真实事件,如同手表记录时间。也就是说不管程序在用户态还是核心态用了多少处理器时间它都记录。当这个计时器用尽,发送SIGALRM消息。 |
ITIMER_VIRTUAL:这个计时器只有进程在用户态运行时才计时。虚拟计时器的30s比实际计时器的30s要长。当虚拟计时器用尽,发送SIGVTALRM消息。 | ||
ITIMER_PROF:这个计时器在进程运行于用户态或由该进程调用而陷入核心态时计时。当这个计时器用尽时,发送SIGPROF消息。 | ||
new_value | it_value:初始时间(第一次执行的时间间隔) | |
it_interval:重复间隔 | ||
old_value | 用于获取已存在的时钟。 |
3.掷骰子游戏的构想
首先这是一个单机游戏,通过curses库来绘制图形,时钟信号来充当电脑的角色。开始游戏后玩家和电脑都有本金100元,每局下注的金额为固定的10元,通过规则会有1倍、3倍和5倍的赔率。
牌型 | 五倍牌:三颗骰子都相同 |
---|---|
三倍牌:三骰子为顺序排(123、234等) | |
普通牌:除五倍和三倍以外的牌型 | |
游戏规则 | 大倍率的牌型胜过小倍率的牌型 |
牌型相同时,点数大的胜出 |
4.代码
(1)主函数(main.c)
/*main.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include "GameLib.h"
#include "dice.h"
#include "unistd.h"
extern Player player; //玩家
extern Computer computer; //电脑
extern Umpire umpire; //裁判
int main()
{
int c;
char str[10];
dice_init(); //游戏初始化
while((c = getchar()) != 'Q')//按键输入
{
if(c == 'r' && player.status == NoReady) //玩家每局游戏刚开始的时候状态为未准备,输入'r'表示准备完毕
{
player.status = Ready;
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(READY),READY);
refresh();
}
else if(player.status == Ready && c == ' ')//玩家每按一下空格键代表摇一个骰子
{
if(!player.dice1.dice_flag)player.dice1.dice_flag = 1; //骰子1的标志,置1表示骰子数值确定
else if(!player.dice2.dice_flag)player.dice2.dice_flag = 1; //骰子2的标志,置1表示骰子数值确定
else if(!player.dice3.dice_flag)player.dice3.dice_flag = 1; //骰子3的标志,置1表示骰子数值确定
//当三个骰子都确定后,玩家的状态为操作完毕
if(player.dice1.dice_flag &&
player.dice2.dice_flag &&
player.dice3.dice_flag)
{
player.status = Finish;
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(FINISH),FINISH);
}
}
money_rule();//判断输赢
if(player.status == Game_Win)//玩家胜利
{
ClearSCR(1,5,SCR_X/2-1,SCR_Y-11);
ClearSCR(SCR_X/2+1,5,SCR_X/2-1,SCR_Y-11);
ClearSCR(SCR_X*1/4+1,SCR_Y-7+3,SCR_X/2,7-3);
WriteStr(PLAYER_GR_X,PLAYER_GR_Y,strlen(GAME_WIN),GAME_WIN);
WriteStr(COMPUTER_GR_X,COMPUTER_GR_Y,strlen(GAME_FAIL),GAME_FAIL);
WriteStr(SCR_X/2,SCR_Y-3,12,"'Q' to exit");
refresh();
stop_shake();
}
else if(player.status == Game_Fail)//玩家失败
{
ClearSCR(1,5,SCR_X/2-1,SCR_Y-11);
ClearSCR(SCR_X/2+1,5,SCR_X/2-1,SCR_Y-11);
ClearSCR(SCR_X*1/4+1,SCR_Y-7+3,SCR_X/2,7-3);
WriteStr(PLAYER_GR_X,PLAYER_GR_Y,strlen(GAME_FAIL),GAME_FAIL);
WriteStr(COMPUTER_GR_X,COMPUTER_GR_Y,strlen(GAME_WIN),GAME_WIN);
WriteStr(SCR_X/2,SCR_Y-3,12,"'Q' to exit");
refresh();
stop_shake();
}
//当玩家和电脑都准备好时,裁判状态为开始
if(player.status == Ready && computer.status == Ready)
{
umpire.status = Start;
WriteStr(UMPIRE_STATUS_X,UMPIRE_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(UMPIRE_STATUS_X,UMPIRE_STATUS_Y,strlen(GAME_START),GAME_START);
refresh();
}
//裁判状态为结束时,表示游戏结束,并重置各变量
if(umpire.status == Over)
{
umpire.status = NoReady;
player.dice1.dice_flag = 0;
player.dice2.dice_flag = 0;
player.dice3.dice_flag = 0;
player.status = NoReady;
computer.dice1.dice_flag = 0;
computer.dice2.dice_flag = 0;
computer.dice3.dice_flag = 0;
computer.status = NoReady;
computer.ready_ttg = computer.ready_ttm;
DrawDice(player.dice1.pos_x,player.dice1.pos_y,'#','?');
DrawDice(player.dice2.pos_x,player.dice2.pos_y,'#','?');
DrawDice(player.dice3.pos_x,player.dice3.pos_y,'#','?');
DrawDice(computer.dice1.pos_x,computer.dice1.pos_y,'#','?');
DrawDice(computer.dice2.pos_x,computer.dice2.pos_y,'#','?');
DrawDice(computer.dice3.pos_x,computer.dice3.pos_y,'#','?');
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(UMPIRE_STATUS_X,UMPIRE_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(NOREADY),NOREADY);
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(NOREADY),NOREADY);
}
//当玩家和电脑都操作完毕后,计算本局输赢
if(player.status == Finish && computer.status == Finish)
{
dice_rule();//计算输赢并计算金钱收益
if(player.status == Win)//玩家本局胜利
{
if(player.dice_status == Ordinary)//普通牌型
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(WIN),WIN);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(FAIL),FAIL);
}
else if(player.dice_status == Three_Times)//三倍
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(THREE_TIMES),THREE_TIMES);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(FAIL),FAIL);
}
else if(player.dice_status == Five_Times)//五倍
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(FIVE_TIMES),FIVE_TIMES);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(FAIL),FAIL);
}
sprintf(str,"%d",player.dice_total);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(str),str);
sprintf(str,"%d",computer.dice_total);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(str),str);
sprintf(str,"%d",player.money);
WriteStr(PLAYER_MONEY_X,PLAYER_MONEY_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_MONEY_X,PLAYER_MONEY_Y,strlen(str),str);
sprintf(str,"%d",computer.money);
WriteStr(COMPUTER_MONEY_X,COMPUTER_MONEY_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_MONEY_X,COMPUTER_MONEY_Y,strlen(str),str);
refresh();
}
else if(computer.status == Win)//电脑本局胜利
{
if(computer.dice_status == Ordinary)//普通牌型
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(FAIL),FAIL);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(WIN),WIN);
}
else if(computer.dice_status == Three_Times)//三倍
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(FAIL),FAIL);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(THREE_TIMES),THREE_TIMES);
}
else if(computer.dice_status == Five_Times)//五倍
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(FAIL),FAIL);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(TBLANK),TBLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(FIVE_TIMES),FIVE_TIMES);
}
sprintf(str,"%d",player.dice_total);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(str),str);
sprintf(str,"%d",computer.dice_total);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(str),str);
sprintf(str,"%d",player.money);
WriteStr(PLAYER_MONEY_X,PLAYER_MONEY_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_MONEY_X,PLAYER_MONEY_Y,strlen(str),str);
sprintf(str,"%d",computer.money);
WriteStr(COMPUTER_MONEY_X,COMPUTER_MONEY_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_MONEY_X,COMPUTER_MONEY_Y,strlen(str),str);
refresh();
}
else if(player.status == Draw && computer.status == Draw)//本局平局
{
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_RESULT_X,PLAYER_RESULT_Y,strlen(DRAW),DRAW);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_RESULT_X,COMPUTER_RESULT_Y,strlen(DRAW),DRAW);
sprintf(str,"%d",player.dice_total);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(PLAYER_TOTAL_X,PLAYER_TOTAL_Y,strlen(str),str);
sprintf(str,"%d",computer.dice_total);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_TOTAL_X,COMPUTER_TOTAL_Y,strlen(str),str);
refresh();
}
umpire.status = Over;//计算本局输赢结束后表示游戏结束,裁判状态设置为结束
WriteStr(UMPIRE_STATUS_X,UMPIRE_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(UMPIRE_STATUS_X,UMPIRE_STATUS_Y,strlen(GAME_OVER),GAME_OVER);
}
}
dice_over();//结束游戏
return 0;
}
(2)通用库(GameLib.c和GameLib.h)
/*GameLib.h*/
#ifndef GAMELIB_H_COMMON
#define GAMELIB_H_COMMON
#include <stdio.h>
#include <curses.h>
/*Draw*/
#define HL 0 //横线
#define VL 1 //直线
/****************************************************************
* 函数名:void DrawLine(int how,int x,int y,int len,char ch)
* 功 能:画线
* 返回值:无
* 参数值:int how:HL表示画横线,VL表示画竖线
* int x,y:起始点坐标
* int len:线长度
* char ch:填充的字符
****************************************************************/
void DrawLine(int how,int x,int y,int len,char ch);
/*********************************************************************
* 函数名:void DrawSquare(int x,int y,int width,int high,char ch)
* 功 能:画方框
* 返回值:无
* 参数值:int x,y:起始点坐标
* int width,high:宽高
* char ch:填充的字符
*********************************************************************/
void DrawSquare(int x,int y,int width,int high,char ch);
/****************************************************************
* 函数名:void DrawDice(int x,int y,char ch,char number)
* 功 能:画骰子
* 返回值:无
* 参数值:int x,y:骰子数值坐标
* char ch:填充的字符
* char number:骰子数值
****************************************************************/
void DrawDice(int x,int y,char ch,char number);
/*Color*/
/****************************************************************
* 函数名:int CheckDisplay(void);
* 功 能:判断终端是否支持颜色显示
* 返回值:0:失败 1:成功
* 参数值:无
****************************************************************/
int CheckDisplay(void);
/****************************************************************
* 函数名:void SetColor(int foreColor,int backColor)
* 功 能:设置颜色组合
* 返回值:无
* 参数值:int foreColor:前景色
* int backColor:背景色
****************************************************************/
void SetColor(int foreColor,int backColor);
/****************************************************************
* 函数名:void color(void)
* 功 能:开启颜色显示
* 返回值:无
* 参数值:无
****************************************************************/
void color(void);
/****************************************************************
* 函数名:void nocolor(void)
* 功 能:关闭颜色显示
* 返回值:无
* 参数值:无
****************************************************************/
void nocolor(void);
/****************************************************************
* 函数名:void reverse(void)
* 功 能:开启反色显示
* 返回值:无
* 参数值:无
****************************************************************/
void reverse(void);
/****************************************************************
* 函数名:void noreverse(void)
* 功 能:关闭反色显示
* 返回值:无
* 参数值:无
****************************************************************/
void noreverse(void);
/****************************************************************
* 函数名:void blink(void)
* 功 能:开始闪烁显示
* 返回值:无
* 参数值:无
****************************************************************/
void blink(void);
/****************************************************************
* 函数名:void noblink(void)
* 功 能:关闭闪烁显示
* 返回值:无
* 参数值:无
****************************************************************/
void noblink(void);
/*Word*/
/****************************************************************
* 函数名:void WriteCh(int x,int y,char ch)
* 功 能:写字符
* 返回值:无
* 参数值:int x,y:坐标
* char ch:填充的字符
****************************************************************/
void WriteCh(int x,int y,char ch);
/****************************************************************
* 函数名:void WriteStr(int x,int y,int len,char *str)
* 功 能:写字符串
* 返回值:无
* 参数值:int x,y:坐标
* int len:字符串长度
* char *str:填充的字符串
****************************************************************/
void WriteStr(int x,int y,int len,char *str);
/*Clear*/
/****************************************************************
* 函数名:void ClearSCR(int x,int y,int width,int high)
* 功 能:清除屏幕
* 返回值:无
* 参数值:int x,y:起始坐标
* int width,high:宽高
****************************************************************/
void ClearSCR(int x,int y,int width,int high);
#endif
/*GameLib.c*/
#include <stdio.h>
#include <stdlib.h>
#include "GameLib.h"
/****************************************************************
* 函数名:void DrawLine(int how,int x,int y,int len,char ch)
* 功 能:画线
* 返回值:无
* 参数值:int how:HL表示画横线,VL表示画竖线
* int x,y:起始点坐标
* int len:线长度
* char ch:填充的字符
****************************************************************/
void DrawLine(int how,int x,int y,int len,char ch){
int i;
if(!how)//Horizontal line
{
for(i=0;i<=len;i++)
{
mvaddch(y,x+i,ch);
}
}
else//Vertical line
{
for(i=0;i<=len;i++)
{
mvaddch(y+i,x,ch);
}
}
}
/*********************************************************************
* 函数名:void DrawSquare(int x,int y,int width,int high,char ch)
* 功 能:画方框
* 返回值:无
* 参数值:int x,y:起始点坐标
* int width,high:宽高
* char ch:填充的字符
*********************************************************************/
void DrawSquare(int x,int y,int width,int high,char ch){
int i;
for(i=x;i<=(x+width);i++)
{
mvaddch(y, i, ch);
mvaddch(y+high, i, ch);
}
for(i=y;i<=(y+high);i++)
{
mvaddch(i, x, ch);
mvaddch(i, x+width, ch);
}
}
/****************************************************************
* 函数名:void DrawDice(int x,int y,char ch,char number)
* 功 能:画骰子
* 返回值:无
* 参数值:int x,y:骰子数值坐标
* char ch:填充的字符
* char number:骰子数值
****************************************************************/
void DrawDice(int x,int y,char ch,char number){
int i,sx,sy;
mvaddch(y,x,number);
sx = x - 2;
sy = y - 1;
for(i=0;i<5;i++)
{
mvaddch(sy,sx+i,ch);
mvaddch(sy+2,sx+i,ch);
}
for(i=0;i<3;i++)
{
mvaddch(sy+i,sx,ch);
mvaddch(sy+i,sx+4,ch);
}
}
/****************************************************************
* 函数名:int CheckDisplay(void);
* 功 能:判断终端是否支持颜色显示
* 返回值:0:失败 1:成功
* 参数值:无
****************************************************************/
int CheckDisplay(void)
{
return start_color();
}
/****************************************************************
* 函数名:void SetColor(int foreColor,int backColor)
* 功 能:设置颜色组合
* 返回值:无
* 参数值:int foreColor:前景色
* int backColor:背景色
****************************************************************/
void SetColor(int foreColor,int backColor)
{
init_pair(1,foreColor,backColor);
}
/****************************************************************
* 函数名:void color(void)
* 功 能:开启颜色显示
* 返回值:无
* 参数值:无
****************************************************************/
void color(void)
{
attron(COLOR_PAIR(1));
}
/****************************************************************
* 函数名:void nocolor(void)
* 功 能:关闭颜色显示
* 返回值:无
* 参数值:无
****************************************************************/
void nocolor(void)
{
attroff(COLOR_PAIR(1));
}
/****************************************************************
* 函数名:void reverse(void)
* 功 能:开启反色显示
* 返回值:无
* 参数值:无
****************************************************************/
void reverse(void)
{
attron(A_REVERSE);
}
/****************************************************************
* 函数名:void noreverse(void)
* 功 能:关闭反色显示
* 返回值:无
* 参数值:无
****************************************************************/
void noreverse(void)
{
attroff(A_REVERSE);
}
/****************************************************************
* 函数名:void blink(void)
* 功 能:开始闪烁显示
* 返回值:无
* 参数值:无
****************************************************************/
void blink(void)
{
attron(A_BLINK);
}
/****************************************************************
* 函数名:void noblink(void)
* 功 能:关闭闪烁显示
* 返回值:无
* 参数值:无
****************************************************************/
void noblink(void)
{
attroff(A_BLINK);
}
/****************************************************************
* 函数名:void WriteCh(int x,int y,char ch)
* 功 能:写字符
* 返回值:无
* 参数值:int x,y:坐标
* char ch:填充的字符
****************************************************************/
void WriteCh(int x,int y,char ch)
{
mvaddch(y,x,ch);
}
/****************************************************************
* 函数名:void WriteStr(int x,int y,int len,char *str)
* 功 能:写字符串
* 返回值:无
* 参数值:int x,y:坐标
* int len:字符串长度
* char *str:填充的字符串
****************************************************************/
void WriteStr(int x,int y,int len,char *str)
{
mvaddstr(y,x-(len/2),str);
}
/****************************************************************
* 函数名:void ClearSCR(int x,int y,int width,int high)
* 功 能:清除屏幕
* 返回值:无
* 参数值:int x,y:起始坐标
* int width,high:宽高
****************************************************************/
void ClearSCR(int x,int y,int width,int high)
{
int i,j;
for(i=x;i<x+width;i++)
{
for(j=y;j<y+high;j++)
{
mvaddch(j,i,' ');
}
}
}
(3)骰子函数(dice.h和dice.c)
/*dice.h*/
#ifndef DICE_H
#define DICE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include "GameLib.h"
//屏幕坐标
#define SCR_X (COLS-1)
#define SCR_Y (LINES-1)
#define PLAYER_STATUS_X SCR_X*3/8-2
#define PLAYER_STATUS_Y SCR_Y-3
#define PLAYER_MONEY_X SCR_X*1/8
#define PLAYER_MONEY_Y SCR_Y-2
#define PLAYER_TOTAL_X SCR_X*1/4
#define PLAYER_TOTAL_Y SCR_Y-11
#define PLAYER_RESULT_X SCR_X*1/4
#define PLAYER_RESULT_Y (SCR_Y-11)+4
#define PLAYER_GR_X SCR_X*1/4
#define PLAYER_GR_Y (SCR_Y-11)*1/2+4
#define COMPUTER_STATUS_X SCR_X*5/8+2
#define COMPUTER_STATUS_Y SCR_Y-3
#define COMPUTER_MONEY_X SCR_X*7/8
#define COMPUTER_MONEY_Y SCR_Y-2
#define COMPUTER_TOTAL_X SCR_X*3/4
#define COMPUTER_TOTAL_Y SCR_Y-11
#define COMPUTER_RESULT_X SCR_X*3/4
#define COMPUTER_RESULT_Y (SCR_Y-11)+4
#define COMPUTER_GR_X SCR_X*3/4
#define COMPUTER_GR_Y (SCR_Y-11)*1/2+4
#define UMPIRE_STATUS_X SCR_X/2
#define UMPIRE_STATUS_Y SCR_Y-3
//字符串
#define TBLANK " "
#define BLANK " "
#define GAME_START "Game Start"
#define GAME_OVER "Game over"
#define FINISH "Finish"
#define NOREADY "NoReady"
#define READY "Ready"
#define WIN "You Win!"
#define GAME_WIN "You Win The Game!"
#define FAIL "You Fail!"
#define GAME_FAIL "You Lose The Game!"
#define DRAW "Game Graw"
#define THREE_TIMES "You Win Three Times!"
#define FIVE_TIMES "You Win Five Times!"
#define MONEY_ADD "+100"
#define MONEY_DEDUCT "-100"
#define MONEY_NONE "+0"
//ticker = 100ms
#define COMPUTER_READY 20 //2s
#define COMPUTER_DICE_T 10 //1s
#define MAX(a,b) (if(a > b)?(a):(b))
#define MIN(a,b) (if(a < b)?(a):(b))
//骰子倍率
typedef enum _dice_status{
Ordinary=1,
Three_Times,
Five_Times
}Dice_Status;
//成员状态
typedef enum _status{
NoReady=1,
Ready,
Finish,
Start,
Over,
Win,
Fail,
Draw,
Game_Win,
Game_Fail
}Status;
//骰子
typedef struct _dice{
int dice_num; //骰子数值
char dice_flag; //骰子标志
int pos_x, //骰子x坐标
pos_y; //骰子y坐标
}Dice;
//裁判
typedef struct _umpire{
Status status; //裁判状态
unsigned int dice_multiple; //倍率
}Umpire;
//玩家
typedef struct _player{
char name[20]; //玩家名字
int money; //玩家本金
Dice dice1; //骰子
Dice dice2;
Dice dice3;
int dice_total; //骰子数值总和
Status status; //玩家状态
Dice_Status dice_status; //玩家骰子倍数
}Player;
//电脑
typedef struct _computer{
char name[20]; //电脑名称
int money; //电脑本金
Dice dice1; //骰子
Dice dice2;
Dice dice3;
int dice_total; //骰子数值总和
int ready_ttm, //准备时钟初始值
ready_ttg, //准备时钟计数器
dice_ttm, //骰子时钟初始值
dice_ttg; //骰子时钟计数器
Status status; //电脑状态
Dice_Status dice_status; //电脑骰子倍数
}Computer;
/****************************************************************
* 函数名:void dice_init(void)
* 功 能:游戏初始化
* 返回值:无
* 参数值:无
****************************************************************/
void dice_init(void);
/****************************************************************
* 函数名:void dice_over(void)
* 功 能:游戏结束
* 返回值:无
* 参数值:无
****************************************************************/
void dice_over(void);
/****************************************************************
* 函数名:void start_shake(void)
* 功 能:开始摇骰子
* 返回值:无
* 参数值:无
****************************************************************/
void start_shake(void);
/****************************************************************
* 函数名:void stop_shake(void)
* 功 能:停止摇骰子
* 返回值:无
* 参数值:无
****************************************************************/
void stop_shake(void);
/****************************************************************
* 函数名:void dice_rule(void)
* 功 能:判断骰子规则
* 返回值:无
* 参数值:无
****************************************************************/
void dice_rule(void);
/****************************************************************
* 函数名:void dice_shake(int signum)
* 功 能:时钟操作函数
* 返回值:无
* 参数值:int signum:信号
****************************************************************/
void dice_shake(int signum);
/****************************************************************
* 函数名:void money_rule(void)
* 功 能:判断游戏输赢
* 返回值:无
* 参数值:无
****************************************************************/
void money_rule(void);
/****************************************************************
* 函数名:void dice_sort(int *num,int len)
* 功 能:骰子排序
* 返回值:无
* 参数值:int *num:骰子数组
* int len:骰子个数
****************************************************************/
void dice_sort(int *num,int len);
/**************************************************************************
* 函数名:Dice_Status dice_status_judge(int dice1,int dice2,int dice3)
* 功 能:判断牌型
* 返回值:牌型
* 参数值:int dice1,dice2,dice3:骰子数值
**************************************************************************/
Dice_Status dice_status_judge(int dice1,int dice2,int dice3);
/****************************************************************
* 函数名:int set_ticker(int n_msecs)
* 功 能:设置时间间隔器
* 返回值:0:成功 -1:失败
* 参数值:int n_msecs:毫秒
****************************************************************/
int set_ticker(int n_msecs);
#endif
/*dice.c*/
#include "dice.h"
#define random(x) (rand()%x)
#define dice_random() (random(6)+1)
Player player;
Computer computer;
Umpire umpire;
/****************************************************************
* 函数名:void dice_init(void)
* 功 能:游戏初始化
* 返回值:无
* 参数值:无
****************************************************************/
void dice_init()
{
char strmoney[10];
void dice_shake(int);
srand((int)time(0));
initscr();
noecho();
crmode();
umpire.status = NoReady;
umpire.dice_multiple = 1;
strcpy(player.name,"Player1");
player.money = 100;
player.dice1.dice_flag = 0;
player.dice2.dice_flag = 0;
player.dice3.dice_flag = 0;
player.dice_total = 0;
player.dice1.pos_x = SCR_X*1/4;
player.dice1.pos_y = (SCR_Y-11)*1/3+4;
player.dice2.pos_x = SCR_X*1/8;
player.dice2.pos_y = (SCR_Y-11)*2/3+4;
player.dice3.pos_x = SCR_X*3/8;
player.dice3.pos_y = (SCR_Y-11)*2/3+4;
player.status = NoReady;
strcpy(computer.name,"Computer");
computer.money = 100;
computer.dice1.dice_flag = 0;
computer.dice2.dice_flag = 0;
computer.dice3.dice_flag = 0;
computer.dice_total = 0;
computer.dice1.pos_x = SCR_X*3/4;
computer.dice1.pos_y = (SCR_Y-11)*1/3+4;
computer.dice2.pos_x = SCR_X*5/8;
computer.dice2.pos_y = (SCR_Y-11)*2/3+4;
computer.dice3.pos_x = SCR_X*7/8;
computer.dice3.pos_y = (SCR_Y-11)*2/3+4;
computer.ready_ttm = computer.ready_ttg = COMPUTER_READY;
computer.dice_ttm = computer.dice_ttg = COMPUTER_DICE_T;
computer.status = NoReady;
signal(SIGINT, SIG_IGN);
if(CheckDisplay() == OK)
{
DrawSquare(0,0,SCR_X,SCR_Y,'#');
DrawLine(VL,SCR_X/2,3,SCR_Y-9,'#');
DrawLine(VL,SCR_X*1/4,SCR_Y-6,6,'#');
DrawLine(VL,SCR_X*3/4,SCR_Y-6,6,'#');
DrawLine(HL,0,3,SCR_X,'#');
DrawLine(HL,0,SCR_Y-6,SCR_X,'#');
WriteStr(SCR_X/2,1,9,"Dice Game");
WriteStr(7,1,11,"'Q' to EXIT");
WriteStr(SCR_X-10,1,12,"'r' to Ready");
WriteStr(SCR_X-8,2,16,"'Space' to Next");
DrawDice(player.dice1.pos_x,player.dice1.pos_y,'#','?');
DrawDice(player.dice2.pos_x,player.dice2.pos_y,'#','?');
DrawDice(player.dice3.pos_x,player.dice3.pos_y,'#','?');
DrawDice(computer.dice1.pos_x,computer.dice1.pos_y,'#','?');
DrawDice(computer.dice2.pos_x,computer.dice2.pos_y,'#','?');
DrawDice(computer.dice3.pos_x,computer.dice3.pos_y,'#','?');
WriteStr(SCR_X*1/8,SCR_Y-4,strlen(player.name),player.name);
sprintf(strmoney,"%d",player.money);
WriteStr(SCR_X*1/8,SCR_Y-2,strlen(strmoney),strmoney);
WriteStr(SCR_X*7/8,SCR_Y-4,strlen(computer.name),computer.name);
sprintf(strmoney,"%d",computer.money);
WriteStr(SCR_X*7/8,SCR_Y-2,strlen(strmoney),strmoney);
WriteStr(SCR_X/2,SCR_Y-5,6,"Umpire");
WriteStr(PLAYER_STATUS_X,PLAYER_STATUS_Y,strlen(NOREADY),NOREADY);
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(NOREADY),NOREADY);
move(SCR_X,SCR_Y);
refresh();
}
signal(SIGALRM, dice_shake);
set_ticker(100);
}
/****************************************************************
* 函数名:void dice_over(void)
* 功 能:游戏结束
* 返回值:无
* 参数值:无
****************************************************************/
void dice_over(void)
{
set_ticker(0);
endwin();
}
/****************************************************************
* 函数名:void start_shake(void)
* 功 能:开始摇骰子
* 返回值:无
* 参数值:无
****************************************************************/
void start_shake(void)
{
signal(SIGALRM, dice_shake);
set_ticker(100);
}
/****************************************************************
* 函数名:void stop_shake(void)
* 功 能:停止摇骰子
* 返回值:无
* 参数值:无
****************************************************************/
void stop_shake(void)
{
set_ticker(0);
}
/****************************************************************
* 函数名:void dice_shake(int signum)
* 功 能:时钟操作函数
* 返回值:无
* 参数值:int signum:信号
****************************************************************/
void dice_shake(int signum)
{
char randstr[10];
signal(SIGALRM, SIG_IGN);
if(!player.dice1.dice_flag && player.status == Ready)
{
player.dice1.dice_num = dice_random();
sprintf(randstr,"%d",player.dice1.dice_num);
WriteStr(player.dice1.pos_x,player.dice1.pos_y,strlen(randstr),randstr);
//refresh();
}
if(!player.dice2.dice_flag && player.status == Ready)
{
player.dice2.dice_num = dice_random();
sprintf(randstr,"%d",player.dice2.dice_num);
WriteStr(player.dice2.pos_x,player.dice2.pos_y,strlen(randstr),randstr);
//refresh();
}
if(!player.dice3.dice_flag && player.status == Ready)
{
player.dice3.dice_num = dice_random();
sprintf(randstr,"%d",player.dice3.dice_num);
WriteStr(player.dice3.pos_x,player.dice3.pos_y,strlen(randstr),randstr);
//refresh();
}
if(!computer.dice1.dice_flag && computer.status == Ready)
{
computer.dice1.dice_num = dice_random();
sprintf(randstr,"%d",computer.dice1.dice_num);
WriteStr(computer.dice1.pos_x,computer.dice1.pos_y,strlen(randstr),randstr);
//refresh();
}
if(!computer.dice2.dice_flag && computer.status == Ready)
{
computer.dice2.dice_num = dice_random();
sprintf(randstr,"%d",computer.dice2.dice_num);
WriteStr(computer.dice2.pos_x,computer.dice2.pos_y,strlen(randstr),randstr);
//refresh();
}
if(!computer.dice3.dice_flag && computer.status == Ready)
{
computer.dice3.dice_num = dice_random();
sprintf(randstr,"%d",computer.dice3.dice_num);
WriteStr(computer.dice3.pos_x,computer.dice3.pos_y,strlen(randstr),randstr);
//refresh();
}
if(computer.ready_ttg-- == 1)
{
computer.status = Ready;
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(READY),READY);
}
if(computer.status == Ready)
computer.dice_ttg--;
if(computer.dice_ttg == 1)
{
computer.dice_ttg = computer.dice_ttm;
if(!computer.dice1.dice_flag)computer.dice1.dice_flag = 1;
else if(!computer.dice2.dice_flag)computer.dice2.dice_flag = 1;
else if(!computer.dice3.dice_flag)computer.dice3.dice_flag = 1;
if(computer.dice1.dice_flag &&
computer.dice2.dice_flag &&
computer.dice3.dice_flag)
{
computer.status = Finish;
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(BLANK),BLANK);
WriteStr(COMPUTER_STATUS_X,COMPUTER_STATUS_Y,strlen(FINISH),FINISH);
}
}
move(SCR_Y,SCR_X);
refresh();
signal(SIGALRM, dice_shake);
}
/****************************************************************
* 函数名:void money_rule(void)
* 功 能:判断游戏输赢
* 返回值:无
* 参数值:无
****************************************************************/
void money_rule(void)
{
if(player.money <= 0)
{
player.status = Game_Fail;
}
else if(computer.money <= 0)
{
player.status = Game_Win;
}
}
/****************************************************************
* 函数名:void dice_rule(void)
* 功 能:判断骰子规则
* 返回值:无
* 参数值:无
****************************************************************/
void dice_rule(void)
{
player.dice_status = dice_status_judge(player.dice1.dice_num,
player.dice2.dice_num,
player.dice3.dice_num);
computer.dice_status = dice_status_judge(computer.dice1.dice_num,
computer.dice2.dice_num,
computer.dice3.dice_num);
player.dice_total = 0;
player.dice_total += player.dice1.dice_num;
player.dice_total += player.dice2.dice_num;
player.dice_total += player.dice3.dice_num;
computer.dice_total = 0;
computer.dice_total += computer.dice1.dice_num;
computer.dice_total += computer.dice2.dice_num;
computer.dice_total += computer.dice3.dice_num;
if((player.dice_status == Ordinary && computer.dice_status == Ordinary) ||
(player.dice_status == Three_Times && computer.dice_status == Three_Times) ||
(player.dice_status == Five_Times && computer.dice_status == Five_Times))
{
if(player.dice_total > computer.dice_total)
{
player.status = Win;
computer.status = Fail;
}
else if(player.dice_total < computer.dice_total)
{
player.status = Fail;
computer.status = Win;
}
else
{
player.status = Draw;
computer.status = Draw;
}
}
else if((player.dice_status == Three_Times && computer.dice_status == Ordinary) ||
(player.dice_status == Five_Times && computer.dice_status == Ordinary))
{
player.status = Win;
computer.status = Fail;
}
else if((player.dice_status == Ordinary && computer.dice_status == Three_Times) ||
(player.dice_status == Ordinary && computer.dice_status == Five_Times))
{
player.status = Fail;
computer.status = Win;
}
else if(player.dice_status == Three_Times && computer.dice_status == Five_Times)
{
player.status = Fail;
computer.status = Win;
}
else if(player.dice_status == Five_Times && computer.dice_status == Three_Times)
{
player.status = Win;
computer.status = Fail;
}
if(player.status == Win)
{
if(player.dice_status == Ordinary)
umpire.dice_multiple = 1;
else if(player.dice_status == Three_Times)
umpire.dice_multiple = 3;
else if(player.dice_status == Five_Times)
umpire.dice_multiple = 5;
player.money += 10 * umpire.dice_multiple;
computer.money -= 10 * umpire.dice_multiple;
}
else if(computer.status == Win)
{
if(computer.dice_status == Ordinary)
umpire.dice_multiple = 1;
else if(computer.dice_status == Three_Times)
umpire.dice_multiple = 3;
else if(computer.dice_status == Five_Times)
umpire.dice_multiple = 5;
player.money -= 10 * umpire.dice_multiple;
computer.money += 10 * umpire.dice_multiple;
}
else if(player.status == Draw && computer.status == Draw)
{
;
}
}
/****************************************************************
* 函数名:int set_ticker(int n_msecs)
* 功 能:设置时间间隔器
* 返回值:0:成功 -1:失败
* 参数值:int n_msecs:毫秒
****************************************************************/
int set_ticker(int n_msecs)
{
struct itimerval new_timeset;
long n_sec,n_usecs;
n_sec = n_msecs / 1000;
n_usecs = (n_msecs % 1000) * 1000L;
new_timeset.it_interval.tv_sec = n_sec;
new_timeset.it_interval.tv_usec = n_usecs;
new_timeset.it_value.tv_sec = n_sec;
new_timeset.it_value.tv_usec = n_usecs;
return setitimer(ITIMER_REAL,&new_timeset,NULL);
}
/**************************************************************************
* 函数名:Dice_Status dice_status_judge(int dice1,int dice2,int dice3)
* 功 能:判断牌型
* 返回值:牌型
* 参数值:int dice1,dice2,dice3:骰子数值
**************************************************************************/
Dice_Status dice_status_judge(int dice1,int dice2,int dice3)
{
int i,j;
int num[3]={0,0,0};
char str[10];
num[0] = dice1;
num[1] = dice2;
num[2] = dice3;
dice_sort(num,3);
if(num[2] == num[1]+1 && num[1] == num[0]+1 && num[0] == num[2]-2)
{
return Three_Times;
}
if(dice1 == dice2 && dice2 == dice3)
return Five_Times;
return Ordinary;
}
/****************************************************************
* 函数名:void dice_sort(int *num,int len)
* 功 能:骰子排序
* 返回值:无
* 参数值:int *num:骰子数组
* int len:骰子个数
****************************************************************/
void dice_sort(int *num,int len)
{
int i,j;
int temp;
for(i=0;i<len-1;i++)
for(j=i+1;j<len;j++)
{
if(num[i] > num[j])
{
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
}
4.操作
(1)编译:gcc main.c GameLib.c dice.c -l curses -o main
(2)运行:./main
(3)游戏操作:进入游戏后,按‘r’表示准备,空格摇骰子,‘Q’退出游戏。当其中一方的金钱数小于等于0时,另一方游戏胜利。
(4)源码下载:https://download.csdn.net/download/q1449516487/10749082
(5)游戏截图: