28 Ekim 2013 Pazartesi

C de Play Fair Şifrelemesi

Bu programda PLAY FAİR şifrelemesinin C kodunu yazacağız.

Kodun Kısa Açıklaması:


Kullanıcıdan anahtar metnini istiyoruz ve metnin uzunluğunu hesaplıyoruz. Bu programda öteleme işlemlerini kullanacağımız için her dizinin bitiş indisini tutuyoruz. Anahtarı aldıktan sonra içinde tekrar eden harfleri siliyoruz. Bu silme işlemini de bahsettiğimiz gibi sola bir kere öteleme yaparak hallediyoruz. Tekrarları sildikten sonra bu dizinin harflerini başta tanımladığımız alfabe dizisinden çıkartıyoruz. Tekrarları sildiğimiz dizinin elemanlarını alfabe dizisinin başına kopyalamamız gerekiyor. Bunun için de alfabe dizisini sağa doğru ötelememiz gerekiyor(tekrarsız kalan harf sayısı kadar). Alfabe dizisinin başına gerekli kopyalamaları yaptıktan sonra bu diziyi tabloya atıyoruz.

Kullanıcıdan şifrelenecek metni girmesini istiyoruz ve ikili olarak kontrole başlıyoruz. İkililerden aynı karakter olan varsa arasına yine öteleme işlemi yaparak ‘X’ karakterini yerleştiriyoruz. Tüm diziye bunu uyguladıktan sonra eğer en son eleman tek kalmışsa dizi sonuna da ‘Z’ karakterini ekliyoruz. Fakat bu son eleman da ‘Z’ ise programımızın sonsuz döngüye girmesini engellemek için ‘X’ karakterini ekliyoruz. Şifreleme işlemine geldiğinde ise her ikili karakterleri bir anda tabloda arıyoruz. Bulduğumuz karakterlerin adreslerini tablo adlı 2x2 lik matriste tutuyoruz. Örneğin HC ikilisini arıyoruz ve bulduğumuzda H karakterinin satır numarasını tutac[0][0] ’a H karakterinin sutun numarasını  tutac[0][1] ‘e ;  C karakterinin satır numarasını tutac[1][0] ’a C karakterinin sutun numarasını  tutac[1][1] ‘e  kaydediyoruz. Daha sonra bunların aynı satırda-sütunda olup olmadığına bu tutaç matrisini kullanarak bakıyoruz ve hemen şifrelenmiş şeklini şifrelenmiş string’i tutacak diziye atıyoruz. Bu işlemleri şifrelenecek string’in sonuna kadar yapıyoruz ve şifreyi ekrana yazdırıyoruz.

Kodun Ayrıntılı Açıklaması:


     Problemin çözüm kısmında öncelikle kullanıcıdan anahtar olacak metni büyük harflerle girmesini istiyoruz ve strlen fonksiyonunu kullanarak girilen dizinin son karakterinin indisini buluyoruz. Daha sonra ilk işimiz girilen bu anahtardaki tekrar eden harfleri çıkartmaktır. Bunu da bir while döngüsü kullanarak yapıyoruz. While döngüsünde aynı harflerin olup olmadığına bakıyoruz. Eğer aynı harfler varsa ikinci olarak bulunan harfi silmemiz gerekiyor. Bu işlemi de o harfin olduğu yere bir kere öteleyerek yapıyoruz. Burada ötelemeden sonra i değişkenini bir azaltmamızın sebebi sildiğimiz harfin üstüne aynı harf geldiği zaman tekrar silmesi gerektiğidir.

     Bahsettiğim başa dönme olayından dolayı bu işlemleri en başta for ile değil de while ile yaptık çünkü for döngüsündeki i değişkenine müdahale etmemiz gerekecekti ve for döngüsünde bu azaltma işlemini yapmak hiç sağlıklı değildir.

     Anahtar dizimizdeki tekrarlı harfleri çıkarttıktan sonra geriye kalan harfleri alfabe dizisinden çıkartmamız gerekiyor çünkü tablomuza alfabede kalan harfleri sırayla ekleyeceğiz.
Tabloya ekleyeceğimiz harfleri alfabe dizisinden alacağız. Bu yüzden sırayla, önce tekrar eden harfleri çıkarttığımız dizideki harfleri alfabe dizisine almalıyız. Bunu da yapmak için öncelikle alfabeden sildiğimiz harf kadar sağa öteleme yapmalıyız ki alfabe dizisinin başına tekrarsız harfleri ekleyebilelim.

     Öteleme işlemini yaptıktan sonra anahtar dizisinde kalan harfleri sırayla alfabe dizisine atıyoruz. Artık alfabe dizisini tabloya atarak şifre metinini kullanıcıdan istiyoruz.

     Bu bölümde öncelikle girilen string’i ikili parçalara ayırıp aynı harf ikililerinin olup olmadığına bakıyoruz. Eğer böyle ikililer varsa o ikililerin arasına ‘X’ karakterini yerleştiriyoruz.  Bu işlemi dizinin sonuna kadar yapıyoruz. Bu işlemleri tamamladıktan sonra eğer en sonda tek karakter kaldıysa onu  ikili yapmak için string’in sonuna ‘Z’ ekliyoruz ve dizinin uzunluğunu bir arttırıyoruz. Eğer son eleman da ‘Z’ ise dizinin sonuna sonsuz döngüyü engellemek için ‘X’ karakterini ekleriz.  Dizilerde son elemanı tutmaktaki amaç öteleme yaptığımız zaman kalan elemanların da diziye dâhil olduğu fakat kullanılmadığından dolayı dizinin asıl son elemanını bulabilmemiz. Görsel amaçlı olarak kullanıcıya burada bir de şifrelenecek string’in son halini gösteriyoruz.

     En son olarak geriye string’i şifrelemek kalıyor. İ değişkenini 0’dan dizi uzunluğuna kadar ikişer olarak arttırıyoruz. Bunu yapmamızdaki amaç her ikilileri bir adımda bulacağımız için teker teker gitmeye gerek kalmamasıdır. Tutaç adlı 2x2 lik matrisimiz bize bulunan harflerin tablodaki indislerini gösterecektir.

Örneğin:

2
4
1
3




     Yukarıdaki tablo bulunan birinci harfin satır sayısının 2 Sütun sayısının 4 olduğunu, ikinci harfin de satır sayısının 1 sütun sayısının 3 olduğunu gösteriyor.

     Programın devamında24’e kadar giden bir t değişkeni tanımladık. Bu bize bulunduğumuz satır ve sütunu verecek. Eğer burada for döngüsü kullansaydık her eleman için 25 elemanı da kontrol etmek zorunda kalacaktık. Örneğin t=13 durumunda satır sayısını 13/5 den 2, sütun sayısını da 13 (mod5 )‘ten 3 olarak bulacağız. Şifrelenecek iki harfin de Satır ve sütun numaralarını bulduktan sonra aynı satır-sütunda olduğuna ya da olmadığına bakıyoruz. Eğer aynı satırdalarsa yanlarındaki, aynı sütundalarsa altlarındaki, ikisi de değilse köşelerindeki elemanları alıyoruz. Bunu tüm stringi dolaşarak yapıyoruz ve bulduğumuz her şifreli harfleri şifre için tanımladığımız diziye atıyoruz. En son da şifrelenmiş string’i ekrana yazdırıyoruz ve programımızı bitiriyoruz. 

Programın Kaynak Kodu:







#include <stdio.h>
#include <stdlib.h>

int main() {
	char tablo[5][5];
	char anahtar[25];//GİRİLECEK ANAHTAR İÇİN KULLANILACAK DİZİ
	char sifrelenmis_dizi[25];//ŞİFRELENEN HARFLERİN YAZILACAĞI DİZİ
	int tutac[2][2];//TABLODA ARANIP-BULUNAN 2 HARFİN ADRESLERİNİN TUTULACAĞI DİZİ
	char alfabe[25]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','X','V','W','Y','Z'};
	char sifrelenecek_dizi[30];//ŞİFRELENMEK İÇİN GİRİLEN DİZİ
	int i,j,k,t,indis;
	int anahtar_dizi_sonu;//ANAHTAR DİZİSİNİN SON İNDİSİNİ TUTAN DEĞİŞKEN
	int alfabe_sonu=24;
	int sifrelenecek_dizi_uzunlugu;
	int sifre_onay=0;
	
	printf("Lutfen anahtar metnini buyuk harflerle giriniz !!\n");
	scanf("%s",&anahtar);
	anahtar_dizi_sonu=strlen(anahtar)-1;
	i=1;
	while(i<=anahtar_dizi_sonu){
		j=0;
				while(anahtar[j]!=anahtar[i] && j<i){
					j++;
				}
				if(j!=i){
						for(k=i;k<anahtar_dizi_sonu;k++){
							anahtar[k]=anahtar[k+1];
						}
						anahtar_dizi_sonu--;
						i--; 
				}
		i++;
	}//AYNI HARFLER BULUNUP DİZİDEN ÇIKARTILIYOR
	for(i=0;i<=anahtar_dizi_sonu;i++){
		j=0;
			while(anahtar[i]!=alfabe[j] ){
				j++;
			}
				for(k=j;k<alfabe_sonu;k++){
					alfabe[k]=alfabe[k+1];
				}
					alfabe_sonu--;
	}//GİRDİĞİMİZ ANAHTARDAKİ HARFLER ALFABEDEN ÇIKARTILIYOR	
	for(i=alfabe_sonu;i>=0;i--)
	{
		alfabe[i+anahtar_dizi_sonu+1]=alfabe[i];
	}//SİLİNEN HARFLER KADAR ALFABE DİZİSİNİ SAĞA ÖTELİYORUZ VE ANAHTARDAKİ HARFLERE YER AÇIYORUZ
	
	for(i=0;i<=anahtar_dizi_sonu;i++){
		alfabe[i]=anahtar[i];
	}//ALFABE DİZİSİNDE AÇTIGIMIZ YERLERE TEKRARSIZ ANAHTAR HARFLERİMİZİ YERLEŞTİRİYORUZ
	printf("\nGirdiginiz anahtarin tekrarsiz harfli formati asagidaki gibidir:\n\n");
	for(i=0;i<=anahtar_dizi_sonu;i++){
		printf("%c",anahtar[i]);
	}
	strcpy(tablo,alfabe);//ALFABE DİZİMİZİ TABLOYA YERLEŞTİRİYORUZ
	printf("\n\nAnahtar yerlestirilmis tablo asagidaki gibidir!!\n\n");
	for(i=0;i<5;i++)
	{
		for(j=0;j<5;j++){
			printf("%c ",tablo[i][j]);
		}
			printf("\n");
	}
	
	
		printf("\nLutfen sifrelenecek metni giriniz!!\n");
		scanf("%s",&sifrelenecek_dizi);
		sifrelenecek_dizi_uzunlugu=strlen(sifrelenecek_dizi);
		indis=0;
		while(indis<sifrelenecek_dizi_uzunlugu){
				if(sifrelenecek_dizi[indis]==sifrelenecek_dizi[indis+1]){
					for(j=strlen(sifrelenecek_dizi)-1;j>indis;j--){
						sifrelenecek_dizi[j+1]=sifrelenecek_dizi[j];
					}
							sifrelenecek_dizi_uzunlugu++;
							sifrelenecek_dizi[indis+1]='X';
		  		}
				else{
					indis=indis+2;
	        	}
		}//AYNI HARF OLAN İKİLİLER VARSA ARAYA 'X' YERLEŞTİRİYORUZ
		
		
			if(sifrelenecek_dizi_uzunlugu%2==1){
				if(sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu-1]=='Z'){
					sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu]='X';
					sifrelenecek_dizi_uzunlugu++;	
				}//EN SON HARF 'Z' İSE SONUNA 'X' EKLİYORUZ
				else{
					sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu]='Z';
					sifrelenecek_dizi_uzunlugu++;	
				}//EN SON HARF TEK KALMIŞSA SONUNA 'Z' EKLİYORUZ
						
			}
		
    
		printf("\nGirdiginiz metnin sifrelenmeye uygun son hali :\n\n");
		for(i=0;i<sifrelenecek_dizi_uzunlugu;i++){
				if(i%2==0&&i!=0){
						printf("-");
				}
				printf("%c",sifrelenecek_dizi[i]);
		}
		printf("\n\n ***ACIKLAMALAR***\n");
		
		for(i=0;i<sifrelenecek_dizi_uzunlugu;i=i+2){
				for(k=i;k<i+2;k++){
					t=0;
						while(sifrelenecek_dizi[k]!=tablo[t/5][t%5]){
								t++;
				   		}
			    		tutac[k%2][0]=t/5;
			    		tutac[k%2][1]=t%5;
				}
			if(tutac[0][0]==tutac[1][0]){
				sifrelenmis_dizi[i]=tablo[tutac[0][0]][(tutac[0][1]+1)%5];
				sifrelenmis_dizi[i+1]=tablo[tutac[1][0]][(tutac[1][1]+1)%5];
	printf("\n%c ve %c ayni satirdadirlar!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
			}//AYNI SATIRDALARSA
			else{
				if(tutac[0][1]==tutac[1][1]){
				
				sifrelenmis_dizi[i]=tablo[(tutac[0][0]+1)%5][tutac[0][1]];
				sifrelenmis_dizi[i+1]=tablo[(tutac[1][0]+1)%5][tutac[1][1]];
       printf("\n%c ve %c ayni sutundadirlar!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
				}//AYNI SUTUNDALARSA
				else{
					sifrelenmis_dizi[i]=tablo[tutac[0][0]][tutac[1][1]];
					sifrelenmis_dizi[i+1]=tablo[tutac[1][0]][tutac[0][1]];
printf("\n%c ve %c ayni satir-sutunda degildirler!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
				}//AYNI SATIR VEYA SUTUNDA DEĞİLLERSE
			}
		}
		printf("\n\nMetnin sifrelenmis hali asagidaki gibidir:\n");
		for(i=0;i<strlen(sifrelenmis_dizi);i++){
				if(i%2==0&&i!=0){
						printf("-");
				}
				printf("%c",sifrelenmis_dizi[i]);
		}	
	return 0;
}

 

Programın Ekran Çıktıları:

























8 Ekim 2013 Salı

C Diliyle Tic Tac Toe Oyunu Yazımı

Tic tac toe oyununun mantığı 3x3 lük karelerde yan yana, alt alta ve ya çapraz biçimde 3’lü seri yapmaya çalışmaktır. Bu örneğimizde de bu oyunun konsol kodunu yazacağız.

Oyunumuzun genel mantığını şöyle özetleyebiliriz:

Kullanıcı oyunu bir yer seçerek başlatacaktır. Daha sonra ise bilgisayar random olarak boş bir yer bulup hamlesini yapacaktır. Bu şekilde sırayla, kullanıcı veya bilgisayar oyunu kazanıp –oyun berabere bitene kadar hamlelerini gerçekleştirecektir.
Kod kısmını ayrıntılı olarak ele almaya başlarsak:

Öncelikle programda kullandığımız değişkenleri ve dizimizi tanımlıyoruz. Daha sonra ekran çıktısı için sade ve anlaşılır bir tablo hazırlamamız gerekiyor. 


Tablomuzu da oluşturduktan sonra sıra geliyor kullanıcıdan girdileri almaya. Burada bir for döngüsü kullanıyoruz. Bu for döngüsü içinde indeks olarak kullandığımız k değişkenini 0’dan 9’a kadar artırıyoruz. Bunu yapmamızdaki neden oyunda maksimum 9 adım olabilmesidir. For döngüsünün ardından k olarak belirlediğimiz indeksin 2’ye göre modunu alıyoruz. Buradaki mantık da k değişkenin ikiye göre modu 0(sıfır) ise sıranın kullanıcıda, 1 ise sıranın bilgisayarda olduğunu belirtmemizdir.

Oyuna hamle sırası kullanıcıda olduğu zaman kullanıcı_girisi adlı fonksiyonumuzu çalıştırıyoruz. Bu fonksiyonumuz ise önce kullanıcıdan satır ve sütun değerlerini istiyor ve hemen ardından while döngüsüne giriyor. Eğer bu girdiğimiz değer 0-2 aralığı dışında veya herhangi dolu bir yere denk geliyorsa ekrana bir bildirim yazdırıp yeni değerler girmesini istiyoruz. Bu işlem kullanıcının geçerli değerleri girene kadar devam ediyor ve en sonunda aldığımız geçerli değişkenlere denk gelen yeri ‘x’ yapıyoruz. Fonksiyon geriye,  düzelttiğimiz ‘matris’ matrisini döndürüyor ardından for döngüsü de k değişkeni bir arttırıp sırayı bilgisayara veriyor.


Bilgisayara sıra geldiğinde ise bilgisayar_girisi adlı fonksiyonumuzu devreye sokuyoruz. Bu fonksiyon da öncelikle rastgele satır ve sütun değerleri seçiyor ardından da yine bir while döngüsüne girdiriyoruz. Burada da boş yer bulana kadar sürekli random fonksiyonuyla satır ve sütun değerleri yakalıyoruz. En son yakaladığımız geçerli yeri bilgisayarı temsilen ‘o’ yapıyoruz. Bu işlemler oyun sonlana kadar devam ediyor.



 Oyunun sonlandığını kontrol etmek için bazı if deyimlerine ihtiyacımız var. Bu if’lerin başlaması için en az 4 el oynanmış olmalıdır, bu yüzden kontrolleri en baştan itibaren değil de k değişkenimizin 4’lenmesinden itibaren başlatıyoruz. Oyunun kazanının olup olmadığını kontrol eden if’ler sekiz adet olmalı çünkü oyunun bir kazananı olup da bitebilmesi için sekiz farklı kombinasyon vardır(3 yatay,3 dikey veya 2 çapraz olarak). Oyunun bittiğini gösteren if deyimlerinin içine birer if deyimi daha eklemeliyiz. Bu son ekleyeceğimiz if’ler ise kazananın bilgisayar mı yoksa kullanıcı mı olduğunu anlamamıza yarayacak. Eğer 3’lü oluşturan karakterler ‘x’ ise kullanıcı,  ’o’ ise bilgisayar kazanmış demektir. Bunların dışında bir de berabere bitme olasılığını da göz önünde bulundurmamız gerekiyor. Oyunların bitme kontrollerini teker teker sekiz adet kontrolle yapacağız. Oyunun berabere bittiğini ise bu kontrollerin sonuna, hamleler için oluşturduğumuz for döngüsünün sonuna gelip gelmediğimizin kontrolünü yaparak anlayabiliriz. Bu kullandığımız if’lerin sonlarına da birer break eklemeliyiz çünkü oyun bittiği zaman programımız sonlanmalıdır.


C Kodunun Tamamı:





#include <stdio.h>
#include <stdlib.h>

char kullanici_giris(char matris[][3]){
int sat,sut;
printf("Oynamak istediginiz satir/sutun giriniz :\n");
scanf("%d%d",&sat,&sut);

while(sat>2||sat<0||sut<0||sut>2||matris[sat][sut]!='-'){
 printf("Girdiginiz aralik gecersiz tekrar girin : \n");
 scanf("%d%d\n",&sat,&sut);
 scanf("%d%d\n",&sat,&sut);
}

matris[sat][sut]='x';//doğru değer girilmiştir, atamayı yapıyoruz
return matris[3][3];//matrisimizi döndürüyoruz 
}

char bilgisayar_giris(char matris[][3]){
int sat,sut;
sat=rand()%3;//satır için ilk random atamyı yapıyoruz
sut=rand()%3;// sutun için ilk randım atamayı yapıyoruz
while(matris[sat][sut]!='-'){//adres doluysa yeniden random atama yapmalıyız
sat=rand()%3;
sut=rand()%3;
}
printf("\nBilgisayarin hamle yaptigi yer\n");
printf("Satir: %d \n",sat);
printf("Sutun: %d \n\n",sut);
matris[sat][sut]='o';//boş yer bulunmuştur, atamayı yapıyoruz
return matris[3][3];//matrisimizi döndürüyoruz
}

int main() {
 int i,j,k,sat,sut;//değişkenlerimiz
 srand(time(NULL));//random fonksiyonun her seferinde 
                               //farklı değer vermesi için gerekli kod
 char matris[3][3]={{'-','-','-'},
      {'-','-','-'},
             {'-','-','-'}};//ilklendirme
printf("  0  1  2\n"); 
for(i=0;i<3;i++){
 printf("%d",i);
 for(j=0;j<3;j++){
  printf(" %c ",matris[i][j]);
 }
 printf("\n");
}//ekran göstergesi

 for(k=0;k<9;k++){//maksimum hamle sayısı 9 olduğundan 9'a kadar döndürürüz
  
  if(k%2==0){//kullanıcının başlaması için mod kullanıyoruz
        kullanici_giris(matris);//kullanıcıdan değer isteme fonksiyonu
      
  }
  else{
  //system("CLS");//ekran temizleyicisi
  bilgisayar_giris(matris);//blgsyrın boş yer bulması ve
      //atama yapması için kullanılan foksiyon 
      printf("  0  1  2\n"); 
       for(i=0;i<3;i++){
          printf("%d",i);
           for(j=0;j<3;j++){
                               printf(" %c ",matris[i][j]);
            }
       printf("\n");
       }//ekran göstergesi
    }
 if(k>3){//oyunun kimin kazandığını ya da oyunun berabere bitip bitmediğini
                                      //kontrol ettiğimiz if dizimleri
  
  if(matris[0][0]==matris[0][1]&&matris[0][1]==matris[0][2]){
   printf("OYUN BITTI!!");
   if(matris[0][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }   
  }
  if(matris[1][0]==matris[1][1]&&matris[1][1]==matris[1][2]){
   printf("OYUN BITTI!!");
   if(matris[1][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[2][0]==matris[2][1]&&matris[2][1]==matris[2][2]){
   printf("OYUN BITTI!!");
   if(matris[2][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[0][0]==matris[1][0]&&matris[1][0]==matris[2][0]){
   printf("OYUN BITTI!!");
   if(matris[0][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[0][1]==matris[1][1]&&matris[1][1]==matris[2][1]){
   printf("OYUN BITTI!!");
   if(matris[0][1]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[0][2]==matris[1][2]&&matris[1][2]==matris[2][2]){
   printf("OYUN BITTI!!");
   if(matris[0][2]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[0][0]==matris[1][1]&&matris[1][1]==matris[2][2]){
   printf("OYUN BITTI!!");
   if(matris[0][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(matris[2][0]==matris[1][1]&&matris[1][1]==matris[0][2]){
   printf("OYUN BITTI!!");
   if(matris[2][0]=='x'){
    printf("TEBRIKLER KAZANDINIZ!!");
    break;
   }
   else{
    printf("MALESEF KAYBETTINIZ");
    break;
   }
  }
  if(k==8){
   printf("OYUN BERABERE BITTI!!");
   break;
  }
  
 }
} 
 return 0;
}

Ekran Çıktıları: