Save the high scrore and high tile info across game launches

This commit is contained in:
Jeremy Rand 2014-07-24 14:21:28 -05:00
parent 956f7ecaca
commit 3acf1bda4e
3 changed files with 111 additions and 18 deletions

View File

@ -65,6 +65,14 @@ void playSound(int8_t freq, int16_t duration)
}
void quitGame(void)
{
shutdownGameEngine();
clrscr();
exit(0);
}
void printInstructions(void)
{
int seed = 0;
@ -89,6 +97,7 @@ void printInstructions(void)
"PRESS ESCAPE OR Q TO QUIT AT ANY TIME.\n"
"PRESS R TO START A NEW GAME.\n"
"PRESS S TO TOGGLE SOUND.\n"
"PRESS H TO SEE THIS INFO AGAIN.\n"
"\n"
"\n"
"\n"
@ -153,8 +162,8 @@ void printValues(void)
void printScore(void)
{
gotoxy(0,20);
printf("CURRENT SCORE: %ld\nTRY TO GET THE %ld TILE!", currentScore(),
nextTarget());
printf("SCORE: %10ld HI-SCORE: %10ld\nTRY TO GET THE %ld TILE!",
currentScore(), highScore(), nextTarget());
}
@ -495,7 +504,8 @@ void handleNextEvent(void)
case CH_ESC:
case 'q':
case 'Q':
exit(0);
quitGame();
break;
case 'r':
case 'R':
@ -507,6 +517,11 @@ void handleNextEvent(void)
case 'S':
gPlaySounds = !gPlaySounds;
break;
case 'h':
case 'H':
printInstructions();
return;
}
}
}

104
game.c
View File

@ -9,6 +9,7 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "game.h"
@ -16,10 +17,10 @@
#define POS_IN_DIR(pos, dir) ((pos) + (dir))
// The maximum which the game supports in any one tile is 2^19 because that is
// the largest number which fits in a 6 character tile. Once this is reached,
// The maximum which the game supports in any one tile is 2^26 because that is
// the largest number which fits in a 8 character tile. Once this is reached,
// the game is won. Note this is a very big number so not a huge restriction.
#define MAX_TILE_VALUE 19
#define MAX_TILE_VALUE 26
#define BLOCKED_TILE_VALUE -1
@ -56,16 +57,30 @@ static char *gValueStrings[MAX_TILE_VALUE + 1] = {
" 65536 ",
" 131072 ",
" 262144 ",
" 524288 "
" 524288 ",
"1048576 ",
"2097152 ",
"4194304 ",
"8388608 ",
"16777216",
"33554432",
"67108864"
};
static tScore gValueScores[MAX_TILE_VALUE + 1] = {
0l, 2l, 4l, 8l, 16l, 32l, 64l, 128l, 256l, 512l, 1024l, 2048l, 4096l,
8192l, 16384l, 32768l, 65536l, 131072l, 262144l, 524288l };
8192l, 16384l, 32768l, 65536l, 131072l, 262144l, 524288l, 1048576l,
2097152l, 4194304l, 8388608l, 16777216l, 33554432l, 67108864l };
struct tScoreRecord {
tScore currentScore;
tScore highScore;
tTileValue highestTile;
} gScoreRecord;
static tScore gCurrentScore;
static tTileValue gNextTarget = 11;
static uint8_t gNumEmptyTiles;
static bool gIsGameWon;
void addRandomTile(void);
@ -78,8 +93,30 @@ static tNewTileCallback gNewTileCallback = NULL;
void initGameEngine(tTileMoveCallback tileMoveCallback,
tNewTileCallback newTileCallback)
{
FILE *scoreFile;
gTileMoveCallback = tileMoveCallback;
gNewTileCallback = newTileCallback;
gScoreRecord.highScore = 0;
gScoreRecord.highestTile = 0;
scoreFile = fopen("a2048score", "rb");
if (scoreFile != NULL) {
fread(&gScoreRecord, sizeof(gScoreRecord), 1, scoreFile);
fclose(scoreFile);
}
}
void shutdownGameEngine(void)
{
FILE *scoreFile;
scoreFile = fopen("a2048score", "wb");
if (scoreFile != NULL) {
fwrite(&gScoreRecord, sizeof(gScoreRecord), 1, scoreFile);
fclose(scoreFile);
}
}
@ -89,8 +126,9 @@ void newGame(void)
tPos x;
tPos y;
gCurrentScore = 0;
gScoreRecord.currentScore = 0;
gNumEmptyTiles = 0;
gIsGameWon = false;
for (pos = 0; pos < NUM_TILES; pos++) {
x = POS_TO_X(pos);
@ -135,6 +173,24 @@ tPos nextPosInDir(tPos pos, tDir dir)
}
void increaseScore(tScore value)
{
gScoreRecord.currentScore += value;
if (gScoreRecord.currentScore > gScoreRecord.highScore)
gScoreRecord.highScore = gScoreRecord.currentScore;
}
void updateMaxTile(tTileValue tileValue)
{
if (gScoreRecord.highestTile < tileValue)
gScoreRecord.highestTile = tileValue;
if (tileValue >= MAX_TILE_VALUE)
gIsGameWon = true;
}
void slideInDirection(tDir dir)
{
tPos pos;
@ -165,15 +221,13 @@ void slideInDirection(tDir dir)
tileValue++;
gTileValues[destPos]++;
gNumEmptyTiles++;
gCurrentScore += gValueScores[tileValue];
increaseScore(gValueScores[tileValue]);
updateMaxTile(tileValue);
// This is a hack to prevent multiple merges from happening to
// the same tile in a single turn. We set the value to a high
// negative (< -1) and then flip the sign bit later.
gTileValues[destPos] = -tileValue;
if (tileValue == gNextTarget)
gNextTarget++;
} else {
gTileValues[destPos] = gTileValues[pos];
}
@ -222,19 +276,39 @@ void addRandomTile(void)
tScore currentScore(void)
{
return gCurrentScore;
return gScoreRecord.currentScore;
}
tScore highScore(void)
{
return gScoreRecord.highScore;
}
tScore highestTarget(void)
{
if (gScoreRecord.highestTile < 11)
return 0;
return gValueScores[gScoreRecord.highestTile];
}
tScore nextTarget(void)
{
return gValueScores[gNextTarget];
tTileValue value = gScoreRecord.highestTile;
if (value < 11)
value = 11;
return gValueScores[value];
}
bool isGameWon(void)
{
return (gNextTarget > MAX_TILE_VALUE);
return gIsGameWon;
}

4
game.h
View File

@ -40,12 +40,16 @@ typedef void (*tNewTileCallback)(tPos at, char *tileString);
extern void initGameEngine(tTileMoveCallback tileMoveCallback,
tNewTileCallback newTileCallback);
extern void shutdownGameEngine(void);
extern void newGame(void);
extern void slideInDirection(tDir dir);
extern tScore currentScore(void);
extern tScore highScore(void);
extern tScore highestTarget(void);
extern tScore nextTarget(void);
extern bool isGameWon(void);