Well I read that you are supposed to use asserts to verify things that are supposed to always be true, which is more or less what I've been using them for.
I've already run into several impossible conditions which were caught by asserts, which reduces the trial and error of debugging significantly.
As for what I'm trying to do, here's my current code
I'm trying to create a game where people alternatately put pieces on a board and the first person to make a square loses, but I haven't gotten very far.
The part that originally prompted my inquiry was on line 171 of the cpp file.
board.h
#ifndef SQPHOBIABOARD_H#define SQPHOBIABOARD_H#include <vector>#include <cstdlib>#include <string>typedef unsigned long u32;typedef std::string str;struct SqMove{ u32 x; u32 y; u32 type; SqMove( u32 nx, u32 ny, u32 nt) : x(nx), y(ny), type(nt) {}};class SqBoard{ const static u32 NUMTYPES = 2; u32 height; u32 width; std::vector<bool> marks; std::vector<bool> safety; bool IsValid( u32 x, u32 y) const { return (x>=0) and (x<width) and (y>=0) and (y<height); } u32 ToIndex( u32 x, u32 y) const { return x + y * width; } bool IsSafe( u32 x, u32 y, u32 type) const; void SetSafety( u32 x, u32 y, u32 type, bool val); bool IsMarked( u32 x, u32 y, u32 type) const; void SetMark( u32 x, u32 y, u32 type, bool val); u32 GetRandom() const { return rand() ^ (rand() << 16); } public: SqBoard( u32 h, u32 w); bool UpdateWithMove( u32 x, u32 y, u32 type); //return val is whether you lost or not bool UpdateWithMove( SqMove newmove); //return val is whether you lost or not u32 MakeRandomMoves( u32 count); //returns number of moves successfully made str ToString() const; u32 Height() const {return height;} u32 Width() const {return width;}};#endif
board.cpp
#include <cassert>#include "board.h"#include <iostream>void EvalAndAssert( int arg ){ assert(arg);}//////////////////////////////////////////////////////////bool SqBoard::IsSafe( u32 x, u32 y, u32 type) const{ assert( IsValid(x,y) ); assert(type<NUMTYPES); return safety.at( type + ToIndex(x,y) * NUMTYPES);}void SqBoard::SetSafety( u32 x, u32 y, u32 type, bool val){ assert( IsValid(x,y) ); assert(type<NUMTYPES); safety.at( type + ToIndex(x,y) * NUMTYPES) = val;}bool SqBoard::IsMarked( u32 x, u32 y, u32 type) const{ assert( IsValid(x,y) ); assert(type<NUMTYPES); return marks.at( type + ToIndex(x,y) * NUMTYPES);}void SqBoard::SetMark( u32 x, u32 y, u32 type, bool val){ assert( IsValid(x,y) ); assert(type<NUMTYPES); marks.at( type + ToIndex(x,y) * NUMTYPES) = val;}/////////////////////////////////////////////////////////////SqBoard::SqBoard( u32 h, u32 w): height(h), width(w),marks(height * width * NUMTYPES, false),safety(height * width * NUMTYPES, true){}bool SqBoard::UpdateWithMove( u32 x, u32 y, u32 type){ assert( IsValid(x,y) ); assert(type<NUMTYPES); //place the new mark on the square SetMark(x,y,type, true); if ( IsSafe(x,y,type) == false) { return true; } else { //if the square was safe, the game is not over //check to see if this move causes any other squares to become dangerous //loop through all posible values for the coordinates of the first side //std::cout << -((int) x) << " , " << width-x << "\n"; for (int i = -(int) x; i < (int) width- (int) x; ++i) { for (int j = -(int) y; j < (int) height- (int) y; ++j) { if (i==0 and j==0) { continue; //make sure square has nonzero side length } //std::cout << i << "," << j << "\n"; //Make sure that all four corners of the square being tested are inside the playable area //first corner if (!IsValid( x + i, y + j ) ) { assert( false ); continue; //This should never happen } //second corner if (!IsValid( x + i + j, y + j - i) ) { continue; } //third corner if (!IsValid( x + j, y - i ) ) { continue; } //Time to see if 3 of the corners have the same type of mark on them, in which case //the fourth corner is dangerous for that type of mark u32 cornercount = 0; if (IsMarked(x,y,type)) { ++cornercount; } if (IsMarked(x + i, y + j,type)) { ++cornercount; } if (IsMarked(x + i + j, y + j - i,type)) { ++cornercount; } if (IsMarked(x + j, y - i,type)) { ++cornercount; } assert( cornercount < 4); assert( cornercount > 0); //Because we just marked the first square! if (cornercount == 3) { //if it is, mark them as unsafe SetSafety(x,y,type,false); SetSafety(x + i, y + j,type,false); SetSafety(x + i + j, y + j - i,type,false); SetSafety(x + j, y - i,type,false); } } } } for( u32 t=0;t<NUMTYPES;++t) { SetSafety(x,y,t,false); //Obviously we can't move to a square that already has a mark on it } return false;}bool SqBoard::UpdateWithMove( SqMove newmove){ return UpdateWithMove( newmove.x, newmove.y, newmove.type );}////////////////////////////////////////////////////////////u32 SqBoard::MakeRandomMoves( u32 count){ std::vector<SqMove> MoveList; u32 movesmade = 0; do { assert(MoveList.size() == 0); //Find all possible safe moves for (u32 x=0;x<width;++x) { for (u32 y=0;y<height;++y) { for (u32 type=0;type<NUMTYPES;++type) { if (IsSafe(x,y,type)) { MoveList.push_back( SqMove(x,y,type) ); } } } } if (MoveList.size() == 0) { //std::cout << "We broke!\n"; break; } u32 RandIndex = GetRandom() % MoveList.size(); assert(!UpdateWithMove( MoveList.at(RandIndex))); //EvalAndAssert(!UpdateWithMove( MoveList.at(RandIndex))); ++movesmade; MoveList.clear(); } while (movesmade < count); return movesmade;}///////////////////////////////////////////////////////////////str SqBoard::ToString() const{ //Converts it to a string for console output. I'll probably remove this once I add a GUI const str pieces = "XO+!~H=*"; str temp; temp = str("+"); temp += str( width, '-'); temp += str("+\n"); for (u32 y=0; y<height; ++y) { temp += str("|"); for (u32 x=0; x<width; ++x) { char nchar = ' '; for (u32 t=0;t<NUMTYPES;++t) { if (IsMarked(x,y,t)) { if (t<pieces.size()) { nchar = pieces.at(t); } } } temp += nchar; } temp += str("|\n"); } temp += str("+"); temp += str( width, '-'); temp += str("+\n"); return temp;}