Start Elkretssimulator


Fixa 5 i rad före Arduino

5 i rad eller luffarschack

Kärt barn har många namn. 5 i rad eller luffarschack eller fritt luffarschack. I professionella sammanhang är spelet modifierat lite och kallas gomoku eller renju. Vi ska inte komplicera något här. Det gäller att få 5 i rad före utmanaren.



Följande behövs

- Arduino
- Kopplingsbräda
- Ett gäng sladdar
- 4 st. 7-segmentdisplayer
- 3 st. pushbuttons
- Resistanser

Utmaningar

Jag har på annat ställe beskrivit hur man kopplar in och får koden att fungera med ett flertal 7-segmentdisplayer om du vill förstå detaljerna här.

Ett annat problem är att vi behöver lite knappar (input) till vårt luffarschack. Minst 3 knappar behövs och det finns inga digitala in/ut-gångar kvar att använda. Men det finns ett antal analoga ingångar och det duger lika bra. Hur vi kan använda en analog ingång till ett flertal knappar är beskrivet här.

Koppla upp brädet

Tryck i 4 stycken displayer enligt nedan. Dessa 4 stycken displayer skall sedan i allt väsentligt parallell-kopplas enligt nedan, sånär som den gemensamma katoden.



Om man tar det systematiskt går det att få rätt. Det är tyvärr ofrånkomligt att det blir ett sladdinferno.







Vi behöver också lite knappar. Eftersom de digitala in/ut -gångarna är slut fixar vi detta genom att använda de analoga ingångarna för knapparna.





Funktion

Datorn börjar alltid i denna version. När datorn lägger sitt drag så blinkar draget. Första draget kommer bli 10, 10.

För att mata in ditt drag trycker du på knapp 1. Du ändrar x-värde med knapp 2 (upp) och 3 (ner). Sen trycker du på knapp 1 igen och ändrar y-värde på samma sätt. Sen trycker du på knapp 1 igen och datorn gör då sitt drag. Dvs;

1. Mata in ditt drag genom att först trycka #1.
2. Justera X upp och ner med knapp #2 och #3.
3. Tryck #1.
4. Justera Y upp och ner med knapp #2 och #3.
5. Tryck #1.

Datorn gör nu sitt drag och allt börjar om.

Om någon har vunnit så kommer displyerna blinka med fyra streck. För att börja om måste man dra ut strömmen och stoppa in den igen - eller ladda över programmet på nytt.

Sådana detaljer behöver förbättras, så du har har göra här! Kan du förbättra programmet, berätta vad du gjorde!

// Beroende på om du anv. gemensam anod (+) eller katod (-) så
// vänder du på nedan. #define _HIGH HIGH ger gemensam katod.
// funktion se http://el.st?5_i_rad

#define _HIGH HIGH
#define _LOW LOW

#define HUMAN 1
#define COMPUTER 2

#define STATE_CHANGE_X 2
#define STATE_CHANGE_Y 3
#define STATE_NEW_MOVE 4

#define BUTTON_UP 1
#define BUTTON_DOWN 2
#define BUTTON_OK 3

int state = STATE_NEW_MOVE;
int x=10,y=10;

int pval = 0;
int val = 0;
int keyPressed = 0;
int countNopress = 0;

bool flash = true;
int timeCtr = 0;
int win=0;

int segPins[8] = {2,3,4,5,6,7,8,9};    
int comPins[4] = {10,11,12,13};
int num[4] = {11,11,11,11};

int segLEDs[12][7]=
{
{1,1,1,1,1,1,0},
{0,1,1,0,0,0,0},
{1,1,0,1,1,0,1},
{1,1,1,1,0,0,1},
{0,1,1,0,0,1,1},
{1,0,1,1,0,1,1},
{1,0,1,1,1,1,1},
{1,1,1,0,0,0,0},
{1,1,1,1,1,1,1},
{1,1,1,0,0,1,1},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,1}
};

char str[32];
char points[15][15];
int ux,uy,pmax=0,uv=0;
char sp[24][24];
int p[81]={
  0, 10, 20, 5,  100,  0,  10,  0,  200,
  3, 15,  0,15,  500,  0,   0,  0,    0,
  0,  0,100, 0,    0,  0, 100,  0, 2500,
  0,  0,  0, 0,    0,  0,   0,  0,    0,
  0,  0,  0, 0, 5000,  0,   0,  0,    0,
  0,  0,  0, 0,    0,  0,   0,  0,    0,
  0,  0, 70, 0,    0,  0,  70,  0,  200,
  0,  0,  0, 0,    0,  0,   0,  0,    0,
  0,  0,  0, 0,    0,  0, 500,  0,20000
  };

int a,b,n=0;

struct calcRet
{
  int winner;
  int cmx;
  int cmy;
};

struct calcRet calc()
{
  int dx,dy,a,b,cmx=0,cmy=0,pnt,i,j,winner=0;
  struct calcRet cRet;
  pmax=-1;
  for(a=4;a<19;a++)
  for(b=4;b<19;b++)
  {
    if(sp[a][b]==0)
    {
      pnt=0;
      for(dx=-1;dx<2;dx++)
      for(dy=-1;dy<2;dy++)
      {
        if((dy!=0)||(dx!=0))
        {
          i=sp[a+dx*4][b+dy*4]*27+sp[a+dx*3][b+dy*3]*9+sp[a+dx*2][b+dy*2]*3+sp[a+dx][b+dy];
          if(p[i]==20000){winner=COMPUTER;};
          j=sp[a-dx*2][b-dy*2]+sp[a-dx][b-dy]*3;
          pnt=pnt+p[i];
          if((j==6)&&((i==53)||(i==26))) {pnt=pnt+90000;};
          if((j==8)&&((i==8)||(i==17)||(i==35)||(i==44)||(i==62)||(i==71))) {pnt=pnt+90000;};
          if(((j==3)||(j==4))&&((i==13)||(i==67))) {pnt=pnt+5000;};
          if((j==4)&&((i==4)||(i==22)||(i==49))) {pnt=pnt+5000;};
          if((i==53)&&(j==0)){pnt=pnt+500;};
          if((i==67)&&(j==0)){pnt=pnt+200;};
        }
      }
      pnt = (pnt+5)/5;
      if(pnt>255) pnt = 255;
      points[a-4][b-4]=pnt;
      if(pnt>pmax)
      {
        pmax=pnt;
        cmx=a;
        cmy=b;
      }
    }
    
    if(sp[a][b]==HUMAN)
    {
      for(dx=-1;dx<2;dx++)
      for(dy=-1;dy<2;dy++)
      {
        if((dy!=0)||(dx!=0))
        {
          i=sp[a+dx*4][b+dy*4]*27+sp[a+dx*3][b+dy*3]*9+sp[a+dx*2][b+dy*2]*3+sp[a+dx][b+dy];
          if(i==40){winner=HUMAN;};
        }
      }      
    }
    
  }

  cRet.winner = winner;
  cRet.cmy = cmy;
  cRet.cmx = cmx;
  return cRet;
}

int button(int v)
{
  if(v>450&&v<550) return BUTTON_UP;
  if(v>600&&v<700) return BUTTON_DOWN;
  if(v>850&&v<950) return  BUTTON_OK;
  return 0;
}

void showXY(int x, int y)
{
  num[3] = 0;
  num[1] = 0;
  if(x>9)
  {
    num[3] = 1;
    x -= 10;
  }
  num[2] = x;

  if(y>9)
  {
    num[1] = 1;
    y -= 10;
  }
  num[0] = y;  
}

int buttonPush(int k)
{
  struct calcRet cRet;
  switch(state)
  {
    case STATE_CHANGE_X:
      if(k == BUTTON_UP)
      {
        x++;
        if(x>15)
          x=1;        
        showXY(x,y);        
      }
      if(k == BUTTON_DOWN)
      {
        x--;  
        if(x<1)
          x=15;      
        showXY(x,y);          
      }
      if(k == BUTTON_OK)
      {
        num[0] = 11;
        num[1] = 11;
        state = STATE_CHANGE_Y;
      }
      break;

    case STATE_CHANGE_Y:
      if(k == BUTTON_UP)
      {
        y++;
        if(y>15)
          y=1;      
        showXY(x,y);
      }
      if(k == BUTTON_DOWN)
      {
        y--;  
        if(y<1)
          y=15;      
        showXY(x,y);
      }
     
      if(k == BUTTON_OK)
      {
        if(sp[x+4][y+4]==0)
        {
          ux=x;
          uy=y;
          sp[ux+4][uy+4]=HUMAN;          
          cRet = calc();
          if(cRet.winner == HUMAN)
          {
            flash = true;
            win = 1;            
          }
          else
          {
            //cRet = calc();
            sp[cRet.cmx][cRet.cmy]=COMPUTER;
            x=cRet.cmx-4;
            y=cRet.cmy-4;
            showXY(x,y);
            flash = true;
            if(cRet.winner == COMPUTER)
              win = 1;            
            else
            {
              state = STATE_NEW_MOVE;
            }
          }
        }
        else
        {
          state = STATE_NEW_MOVE;          
        }
      }      
      break;

    case STATE_NEW_MOVE:    
      if(k == BUTTON_OK)
      {      
        num[2] = 11;
        num[3] = 11;     
        flash = false;
        state = STATE_CHANGE_X;      
      }    
      break;
  }
}

void setup() 
{
  for (int i=0; i<8;i++)
    pinMode(segPins[i],OUTPUT);
    
  for (int i=0; i < 4;i++)
    pinMode(comPins[i],OUTPUT);  
  
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A =  100;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  sei();     

  showXY(x,y);
  sp[x+4][y+4]=COMPUTER;
}

ISR(TIMER1_COMPA_vect)
{
  clear();

  if(flash && timeCtr > 150)
  {
    digit(0,(win==1)?11:10);
    digit(1,(win==1)?11:10);
    digit(2,(win==1)?11:10);
    digit(3,(win==1)?11:10);    
  }
  else
  {
    digit(0,num[0]);
    digit(1,num[1]);
    digit(2,num[2]);
    digit(3,num[3]);
  }

  timeCtr++;
  if(timeCtr > 300)
    timeCtr = 0;

  pval = button(analogRead(0));
    
  if(pval == 0)
  {
    countNopress++;
    if(countNopress > 1)
      val = 0;    
  }
  else
  {
    if(val != pval)
    {
      val = pval;
      countNopress = 0;      
      buttonPush(val);
    }
  }
}

void digit(int d, int num)
{
  for (int d=0; d < 4;d++)
    digitalWrite(comPins[d], _HIGH);

  digitalWrite(comPins[d], _LOW);
  for (int i=0; i<7; i++)
    digitalWrite(segPins[i],segLEDs[num][i]?_HIGH:_LOW);

  delay(50);
}

void clear()
{
  for (int d=0; d < 4;d++)
  {
    digitalWrite(comPins[d], _HIGH);
      for (int i=0; i<7; i++)
        digitalWrite(segPins[i],_LOW);     
  }
}

void loop() 
{
  
}